Static Value-Flow Analysis
cuddInt.c
Go to the documentation of this file.
1 
63 #include "CUDD/util.h"
64 #include "CUDD/cuddInt.h"
65 
66 /*---------------------------------------------------------------------------*/
67 /* Constant declarations */
68 /*---------------------------------------------------------------------------*/
69 
70 
71 /*---------------------------------------------------------------------------*/
72 /* Stucture declarations */
73 /*---------------------------------------------------------------------------*/
74 
75 
76 /*---------------------------------------------------------------------------*/
77 /* Type declarations */
78 /*---------------------------------------------------------------------------*/
79 
80 
81 /*---------------------------------------------------------------------------*/
82 /* Variable declarations */
83 /*---------------------------------------------------------------------------*/
84 
85 #ifndef lint
86 static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.16 2012/02/05 01:07:18 fabio Exp $";
87 #endif
88 
89 
90 /*---------------------------------------------------------------------------*/
91 /* Macro declarations */
92 /*---------------------------------------------------------------------------*/
93 
94 
97 /*---------------------------------------------------------------------------*/
98 /* Static function prototypes */
99 /*---------------------------------------------------------------------------*/
100 
101 static void addVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero);
102 
106 /*---------------------------------------------------------------------------*/
107 /* Definition of exported functions */
108 /*---------------------------------------------------------------------------*/
109 
110 
127 DdNode *
129  DdManager * dd,
130  DdNode * f,
131  DdNode * g,
132  DdNode * h)
133 {
134  DdNode *one,*zero;
135  DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e;
136  unsigned int topf,topg,toph,v;
137 
138  statLine(dd);
139  /* Trivial cases. */
140  if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */
141  return(g);
142  }
143  if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */
144  return(h);
145  }
146 
147  /* From now on, f is known not to be a constant. */
148  addVarToConst(f,&g,&h,one,zero);
149 
150  /* Check remaining one variable cases. */
151  if (g == h) { /* ITE(F,G,G) = G */
152  return(g);
153  }
154  if (cuddIsConstant(g) && cuddIsConstant(h)) {
155  return(DD_NON_CONSTANT);
156  }
157 
158  topf = cuddI(dd,f->index);
159  topg = cuddI(dd,g->index);
160  toph = cuddI(dd,h->index);
161  v = ddMin(topg,toph);
162 
163  /* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */
164  if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) {
165  return(DD_NON_CONSTANT);
166  }
167 
168  /* Check cache. */
170  if (r != NULL) {
171  return(r);
172  }
173 
174  /* Compute cofactors. */
175  if (topf <= v) {
176  v = ddMin(topf,v); /* v = top_var(F,G,H) */
177  Fv = cuddT(f); Fnv = cuddE(f);
178  } else {
179  Fv = Fnv = f;
180  }
181  if (topg == v) {
182  Gv = cuddT(g); Gnv = cuddE(g);
183  } else {
184  Gv = Gnv = g;
185  }
186  if (toph == v) {
187  Hv = cuddT(h); Hnv = cuddE(h);
188  } else {
189  Hv = Hnv = h;
190  }
191 
192  /* Recursive step. */
193  t = Cudd_addIteConstant(dd,Fv,Gv,Hv);
194  if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
196  return(DD_NON_CONSTANT);
197  }
198  e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv);
199  if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
201  return(DD_NON_CONSTANT);
202  }
203  cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t);
204  return(t);
205 
206 } /* end of Cudd_addIteConstant */
207 
208 
224 DdNode *
226  DdManager * dd,
227  DdNode * f,
228  DdNode * g)
229 {
230  DdNode *zero;
231  DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e;
232  unsigned int topf,topg;
233 
234 #ifdef DD_DEBUG
236 #endif
237 
238  statLine(dd);
239  /* Terminal cases. */
240  if (f == DD_ONE(dd) || cuddIsConstant(g)) {
241  return(g);
242  }
243  if (f == (zero = DD_ZERO(dd))) {
244  return(dd->background);
245  }
246 
247 #ifdef DD_DEBUG
248  assert(!cuddIsConstant(f));
249 #endif
250  /* From now on, f and g are known not to be constants. */
251 
252  topf = cuddI(dd,f->index);
253  topg = cuddI(dd,g->index);
254 
255  /* Check cache. */
257  if (r != NULL) {
258  return(r);
259  }
260 
261  /* Compute cofactors. */
262  if (topf <= topg) {
263  Fv = cuddT(f); Fnv = cuddE(f);
264  } else {
265  Fv = Fnv = f;
266  }
267  if (topg <= topf) {
268  Gv = cuddT(g); Gnv = cuddE(g);
269  } else {
270  Gv = Gnv = g;
271  }
272 
273  /* Recursive step. */
274  if (Fv != zero) {
275  t = Cudd_addEvalConst(dd,Fv,Gv);
276  if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
278  return(DD_NON_CONSTANT);
279  }
280  if (Fnv != zero) {
281  e = Cudd_addEvalConst(dd,Fnv,Gnv);
282  if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
284  return(DD_NON_CONSTANT);
285  }
286  }
288  return(t);
289  } else { /* Fnv must be != zero */
290  e = Cudd_addEvalConst(dd,Fnv,Gnv);
291  cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e);
292  return(e);
293  }
294 
295 } /* end of Cudd_addEvalConst */
296 
297 
311 DdNode *
313  DdManager * dd,
314  DdNode * f)
315 {
316  DdNode *res;
317 
318  do {
319  dd->reordered = 0;
320  res = cuddAddCmplRecur(dd,f);
321  } while (dd->reordered == 1);
322  return(res);
323 
324 } /* end of Cudd_addCmpl */
325 
326 
340 int
342  DdManager * dd,
343  DdNode * f,
344  DdNode * g)
345 {
346  DdNode *tmp, *fv, *fvn, *gv, *gvn;
347  unsigned int topf, topg, res;
348 
349  /* Terminal cases. */
350  if (f == g) return(1);
351 
352  statLine(dd);
353  if (cuddIsConstant(f)) {
354  if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g));
355  if (f == DD_MINUS_INFINITY(dd)) return(1);
356  if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */
357  }
358  if (g == DD_PLUS_INFINITY(dd)) return(1);
359  if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */
360 
361  /* Check cache. */
362  tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_addLeq,f,g);
363  if (tmp != NULL) {
364  return(tmp == DD_ONE(dd));
365  }
366 
367  /* Compute cofactors. One of f and g is not constant. */
368  topf = cuddI(dd,f->index);
369  topg = cuddI(dd,g->index);
370  if (topf <= topg) {
371  fv = cuddT(f); fvn = cuddE(f);
372  } else {
373  fv = fvn = f;
374  }
375  if (topg <= topf) {
376  gv = cuddT(g); gvn = cuddE(g);
377  } else {
378  gv = gvn = g;
379  }
380 
381  res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv);
382 
383  /* Store result in cache and return. */
384  cuddCacheInsert2(dd,(DD_CTFP) Cudd_addLeq,f,g,
385  Cudd_NotCond(DD_ONE(dd),res==0));
386  return(res);
387 
388 } /* end of Cudd_addLeq */
389 
390 
391 /*---------------------------------------------------------------------------*/
392 /* Definition of internal functions */
393 /*---------------------------------------------------------------------------*/
394 
395 
409 DdNode *
411  DdManager * dd,
412  DdNode * f,
413  DdNode * g,
414  DdNode * h)
415 {
416  DdNode *one,*zero;
417  DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e;
418  unsigned int topf,topg,toph,v;
419  int index;
420 
421  statLine(dd);
422  /* Trivial cases. */
423 
424  /* One variable cases. */
425  if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */
426  return(g);
427  }
428  if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */
429  return(h);
430  }
431 
432  /* From now on, f is known to not be a constant. */
433  addVarToConst(f,&g,&h,one,zero);
434 
435  /* Check remaining one variable cases. */
436  if (g == h) { /* ITE(F,G,G) = G */
437  return(g);
438  }
439 
440  if (g == one) { /* ITE(F,1,0) = F */
441  if (h == zero) return(f);
442  }
443 
444  topf = cuddI(dd,f->index);
445  topg = cuddI(dd,g->index);
446  toph = cuddI(dd,h->index);
447  v = ddMin(topg,toph);
448 
449  /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */
450  if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
451  r = cuddUniqueInter(dd,(int)f->index,g,h);
452  return(r);
453  }
454  if (topf < v && cuddT(f) == zero && cuddE(f) == one) {
455  r = cuddUniqueInter(dd,(int)f->index,h,g);
456  return(r);
457  }
458 
459  /* Check cache. */
460  r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h);
461  if (r != NULL) {
462  return(r);
463  }
464 
465  /* Compute cofactors. */
466  if (topf <= v) {
467  v = ddMin(topf,v); /* v = top_var(F,G,H) */
468  index = f->index;
469  Fv = cuddT(f); Fnv = cuddE(f);
470  } else {
471  Fv = Fnv = f;
472  }
473  if (topg == v) {
474  index = g->index;
475  Gv = cuddT(g); Gnv = cuddE(g);
476  } else {
477  Gv = Gnv = g;
478  }
479  if (toph == v) {
480  index = h->index;
481  Hv = cuddT(h); Hnv = cuddE(h);
482  } else {
483  Hv = Hnv = h;
484  }
485 
486  /* Recursive step. */
487  t = cuddAddIteRecur(dd,Fv,Gv,Hv);
488  if (t == NULL) return(NULL);
489  cuddRef(t);
490 
491  e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv);
492  if (e == NULL) {
493  Cudd_RecursiveDeref(dd,t);
494  return(NULL);
495  }
496  cuddRef(e);
497 
498  r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
499  if (r == NULL) {
500  Cudd_RecursiveDeref(dd,t);
501  Cudd_RecursiveDeref(dd,e);
502  return(NULL);
503  }
504  cuddDeref(t);
505  cuddDeref(e);
506 
507  cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r);
508 
509  return(r);
510 
511 } /* end of cuddAddIteRecur */
512 
513 
526 DdNode *
528  DdManager * dd,
529  DdNode * f)
530 {
531  DdNode *one,*zero;
532  DdNode *r,*Fv,*Fnv,*t,*e;
533 
534  statLine(dd);
535  one = DD_ONE(dd);
536  zero = DD_ZERO(dd);
537 
538  if (cuddIsConstant(f)) {
539  if (f == zero) {
540  return(one);
541  } else {
542  return(zero);
543  }
544  }
545  r = cuddCacheLookup1(dd,Cudd_addCmpl,f);
546  if (r != NULL) {
547  return(r);
548  }
549  Fv = cuddT(f);
550  Fnv = cuddE(f);
551  t = cuddAddCmplRecur(dd,Fv);
552  if (t == NULL) return(NULL);
553  cuddRef(t);
554  e = cuddAddCmplRecur(dd,Fnv);
555  if (e == NULL) {
556  Cudd_RecursiveDeref(dd,t);
557  return(NULL);
558  }
559  cuddRef(e);
560  r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
561  if (r == NULL) {
562  Cudd_RecursiveDeref(dd, t);
563  Cudd_RecursiveDeref(dd, e);
564  return(NULL);
565  }
566  cuddDeref(t);
567  cuddDeref(e);
569  return(r);
570 
571 } /* end of cuddAddCmplRecur */
572 
573 
574 /*---------------------------------------------------------------------------*/
575 /* Definition of static functions */
576 /*---------------------------------------------------------------------------*/
577 
578 
589 static void
591  DdNode * f,
592  DdNode ** gp,
593  DdNode ** hp,
594  DdNode * one,
595  DdNode * zero)
596 {
597  DdNode *g = *gp;
598  DdNode *h = *hp;
599 
600  if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
601  *gp = one;
602  }
603 
604  if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
605  *hp = zero;
606  }
607 
608 } /* end of addVarToConst */
609 
610 
675 /*---------------------------------------------------------------------------*/
676 /* Constant declarations */
677 /*---------------------------------------------------------------------------*/
678 
679 /* Annealing parameters */
680 #define BETA 0.6
681 #define ALPHA 0.90
682 #define EXC_PROB 0.4
683 #define JUMP_UP_PROB 0.36
684 #define MAXGEN_RATIO 15.0
685 #define STOP_TEMP 1.0
686 
687 /*---------------------------------------------------------------------------*/
688 /* Stucture declarations */
689 /*---------------------------------------------------------------------------*/
690 
691 
692 /*---------------------------------------------------------------------------*/
693 /* Type declarations */
694 /*---------------------------------------------------------------------------*/
695 
696 
697 /*---------------------------------------------------------------------------*/
698 /* Variable declarations */
699 /*---------------------------------------------------------------------------*/
700 
701 //#ifndef lint
702 //static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.15 2012/02/05 01:07:18 fabio Exp $";
703 //#endif
704 
705 #ifdef DD_STATS
706 extern int ddTotalNumberSwapping;
707 extern int ddTotalNISwaps;
708 static int tosses;
709 static int acceptances;
710 #endif
711 
712 /*---------------------------------------------------------------------------*/
713 /* Macro declarations */
714 /*---------------------------------------------------------------------------*/
715 
716 
719 /*---------------------------------------------------------------------------*/
720 /* Static function prototypes */
721 /*---------------------------------------------------------------------------*/
722 
723 static int stopping_criterion (int c1, int c2, int c3, int c4, double temp);
724 static double random_generator (void);
725 static int ddExchange (DdManager *table, int x, int y, double temp);
726 static int ddJumpingAux (DdManager *table, int x, int x_low, int x_high, double temp);
727 static Move * ddJumpingUp (DdManager *table, int x, int x_low, int initial_size);
728 static Move * ddJumpingDown (DdManager *table, int x, int x_high, int initial_size);
729 static int siftBackwardProb (DdManager *table, Move *moves, int size, double temp);
730 static void copyOrder (DdManager *table, int *array, int lower, int upper);
731 static int restoreOrder (DdManager *table, int *array, int lower, int upper);
732 
736 /*---------------------------------------------------------------------------*/
737 /* Definition of exported functions */
738 /*---------------------------------------------------------------------------*/
739 
740 /*---------------------------------------------------------------------------*/
741 /* Definition of internal functions */
742 /*---------------------------------------------------------------------------*/
743 
744 
760 int
762  DdManager * table,
763  int lower,
764  int upper)
765 {
766  int nvars;
767  int size;
768  int x,y;
769  int result;
770  int c1, c2, c3, c4;
771  int BestCost;
772  int *BestOrder;
773  double NewTemp, temp;
774  double rand1;
775  int innerloop, maxGen;
776  int ecount, ucount, dcount;
777 
778  nvars = upper - lower + 1;
779 
780  result = cuddSifting(table,lower,upper);
781 #ifdef DD_STATS
782  (void) fprintf(table->out,"\n");
783 #endif
784  if (result == 0) return(0);
785 
786  size = table->keys - table->isolated;
787 
788  /* Keep track of the best order. */
789  BestCost = size;
790  BestOrder = ALLOC(int,nvars);
791  if (BestOrder == NULL) {
792  table->errorCode = CUDD_MEMORY_OUT;
793  return(0);
794  }
795  copyOrder(table,BestOrder,lower,upper);
796 
797  temp = BETA * size;
798  maxGen = (int) (MAXGEN_RATIO * nvars);
799 
800  c1 = size + 10;
801  c2 = c1 + 10;
802  c3 = size;
803  c4 = c2 + 10;
804  ecount = ucount = dcount = 0;
805 
806  while (!stopping_criterion(c1, c2, c3, c4, temp)) {
807 #ifdef DD_STATS
808  (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t",
809  temp,size,maxGen);
810  tosses = acceptances = 0;
811 #endif
812  for (innerloop = 0; innerloop < maxGen; innerloop++) {
813  /* Choose x, y randomly. */
814  x = (int) Cudd_Random() % nvars;
815  do {
816  y = (int) Cudd_Random() % nvars;
817  } while (x == y);
818  x += lower;
819  y += lower;
820  if (x > y) {
821  int tmp = x;
822  x = y;
823  y = tmp;
824  }
825 
826  /* Choose move with roulette wheel. */
827  rand1 = random_generator();
828  if (rand1 < EXC_PROB) {
829  result = ddExchange(table,x,y,temp); /* exchange */
830  ecount++;
831 #if 0
832  (void) fprintf(table->out,
833  "Exchange of %d and %d: size = %d\n",
834  x,y,table->keys - table->isolated);
835 #endif
836  } else if (rand1 < EXC_PROB + JUMP_UP_PROB) {
837  result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */
838  ucount++;
839 #if 0
840  (void) fprintf(table->out,
841  "Jump up of %d to %d: size = %d\n",
842  y,x,table->keys - table->isolated);
843 #endif
844  } else {
845  result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */
846  dcount++;
847 #if 0
848  (void) fprintf(table->out,
849  "Jump down of %d to %d: size = %d\n",
850  x,y,table->keys - table->isolated);
851 #endif
852  }
853 
854  if (!result) {
855  FREE(BestOrder);
856  return(0);
857  }
858 
859  size = table->keys - table->isolated; /* keep current size */
860  if (size < BestCost) { /* update best order */
861  BestCost = size;
862  copyOrder(table,BestOrder,lower,upper);
863  }
864  }
865  c1 = c2;
866  c2 = c3;
867  c3 = c4;
868  c4 = size;
869  NewTemp = ALPHA * temp;
870  if (NewTemp >= 1.0) {
871  maxGen = (int)(log(NewTemp) / log(temp) * maxGen);
872  }
873  temp = NewTemp; /* control variable */
874 #ifdef DD_STATS
875  (void) fprintf(table->out,"uphill = %d\taccepted = %d\n",
876  tosses,acceptances);
877  fflush(table->out);
878 #endif
879  }
880 
881  result = restoreOrder(table,BestOrder,lower,upper);
882  FREE(BestOrder);
883  if (!result) return(0);
884 #ifdef DD_STATS
885  fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount);
886  fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount);
887  fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount);
888 #endif
889  return(1);
890 
891 } /* end of cuddAnnealing */
892 
893 
894 /*---------------------------------------------------------------------------*/
895 /* Definition of static functions */
896 /*---------------------------------------------------------------------------*/
897 
911 static int
913  int c1,
914  int c2,
915  int c3,
916  int c4,
917  double temp)
918 {
919  if (STOP_TEMP < temp) {
920  return(0);
921  } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) {
922  return(1);
923  } else {
924  return(0);
925  }
926 
927 } /* end of stopping_criterion */
928 
929 
941 static double
943 {
944  return((double)(Cudd_Random() / 2147483561.0));
945 
946 } /* end of random_generator */
947 
948 
961 static int
963  DdManager * table,
964  int x,
965  int y,
966  double temp)
967 {
968  Move *move,*moves;
969  int tmp;
970  int x_ref,y_ref;
971  int x_next,y_next;
972  int size, result;
973  int initial_size, limit_size;
974 
975  x_ref = x;
976  y_ref = y;
977 
978  x_next = cuddNextHigh(table,x);
979  y_next = cuddNextLow(table,y);
980  moves = NULL;
981  initial_size = limit_size = table->keys - table->isolated;
982 
983  for (;;) {
984  if (x_next == y_next) {
985  size = cuddSwapInPlace(table,x,x_next);
986  if (size == 0) goto ddExchangeOutOfMem;
987  move = (Move *)cuddDynamicAllocNode(table);
988  if (move == NULL) goto ddExchangeOutOfMem;
989  move->x = x;
990  move->y = x_next;
991  move->size = size;
992  move->next = moves;
993  moves = move;
994  size = cuddSwapInPlace(table,y_next,y);
995  if (size == 0) goto ddExchangeOutOfMem;
996  move = (Move *)cuddDynamicAllocNode(table);
997  if (move == NULL) goto ddExchangeOutOfMem;
998  move->x = y_next;
999  move->y = y;
1000  move->size = size;
1001  move->next = moves;
1002  moves = move;
1003  size = cuddSwapInPlace(table,x,x_next);
1004  if (size == 0) goto ddExchangeOutOfMem;
1005  move = (Move *)cuddDynamicAllocNode(table);
1006  if (move == NULL) goto ddExchangeOutOfMem;
1007  move->x = x;
1008  move->y = x_next;
1009  move->size = size;
1010  move->next = moves;
1011  moves = move;
1012 
1013  tmp = x;
1014  x = y;
1015  y = tmp;
1016  } else if (x == y_next) {
1017  size = cuddSwapInPlace(table,x,x_next);
1018  if (size == 0) goto ddExchangeOutOfMem;
1019  move = (Move *)cuddDynamicAllocNode(table);
1020  if (move == NULL) goto ddExchangeOutOfMem;
1021  move->x = x;
1022  move->y = x_next;
1023  move->size = size;
1024  move->next = moves;
1025  moves = move;
1026  tmp = x;
1027  x = y;
1028  y = tmp;
1029  } else {
1030  size = cuddSwapInPlace(table,x,x_next);
1031  if (size == 0) goto ddExchangeOutOfMem;
1032  move = (Move *)cuddDynamicAllocNode(table);
1033  if (move == NULL) goto ddExchangeOutOfMem;
1034  move->x = x;
1035  move->y = x_next;
1036  move->size = size;
1037  move->next = moves;
1038  moves = move;
1039  size = cuddSwapInPlace(table,y_next,y);
1040  if (size == 0) goto ddExchangeOutOfMem;
1041  move = (Move *)cuddDynamicAllocNode(table);
1042  if (move == NULL) goto ddExchangeOutOfMem;
1043  move->x = y_next;
1044  move->y = y;
1045  move->size = size;
1046  move->next = moves;
1047  moves = move;
1048  x = x_next;
1049  y = y_next;
1050  }
1051 
1052  x_next = cuddNextHigh(table,x);
1053  y_next = cuddNextLow(table,y);
1054  if (x_next > y_ref) break;
1055 
1056  if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) {
1057  break;
1058  } else if (size < limit_size) {
1059  limit_size = size;
1060  }
1061  }
1062 
1063  if (y_next>=x_ref) {
1064  size = cuddSwapInPlace(table,y_next,y);
1065  if (size == 0) goto ddExchangeOutOfMem;
1066  move = (Move *)cuddDynamicAllocNode(table);
1067  if (move == NULL) goto ddExchangeOutOfMem;
1068  move->x = y_next;
1069  move->y = y;
1070  move->size = size;
1071  move->next = moves;
1072  moves = move;
1073  }
1074 
1075  /* move backward and stop at best position or accept uphill move */
1076  result = siftBackwardProb(table,moves,initial_size,temp);
1077  if (!result) goto ddExchangeOutOfMem;
1078 
1079  while (moves != NULL) {
1080  move = moves->next;
1081  cuddDeallocMove(table, moves);
1082  moves = move;
1083  }
1084  return(1);
1085 
1086  ddExchangeOutOfMem:
1087  while (moves != NULL) {
1088  move = moves->next;
1089  cuddDeallocMove(table, moves);
1090  moves = move;
1091  }
1092  return(0);
1093 
1094 } /* end of ddExchange */
1095 
1096 
1110 static int
1112  DdManager * table,
1113  int x,
1114  int x_low,
1115  int x_high,
1116  double temp)
1117 {
1118  Move *move;
1119  Move *moves; /* list of moves */
1120  int initial_size;
1121  int result;
1122 
1123  initial_size = table->keys - table->isolated;
1124 
1125 #ifdef DD_DEBUG
1126  assert(table->subtables[x].keys > 0);
1127 #endif
1128 
1129  moves = NULL;
1130 
1131  if (cuddNextLow(table,x) < x_low) {
1132  if (cuddNextHigh(table,x) > x_high) return(1);
1133  moves = ddJumpingDown(table,x,x_high,initial_size);
1134  /* after that point x --> x_high unless early termination */
1135  if (moves == NULL) goto ddJumpingAuxOutOfMem;
1136  /* move backward and stop at best position or accept uphill move */
1137  result = siftBackwardProb(table,moves,initial_size,temp);
1138  if (!result) goto ddJumpingAuxOutOfMem;
1139  } else if (cuddNextHigh(table,x) > x_high) {
1140  moves = ddJumpingUp(table,x,x_low,initial_size);
1141  /* after that point x --> x_low unless early termination */
1142  if (moves == NULL) goto ddJumpingAuxOutOfMem;
1143  /* move backward and stop at best position or accept uphill move */
1144  result = siftBackwardProb(table,moves,initial_size,temp);
1145  if (!result) goto ddJumpingAuxOutOfMem;
1146  } else {
1147  (void) fprintf(table->err,"Unexpected condition in ddJumping\n");
1148  goto ddJumpingAuxOutOfMem;
1149  }
1150  while (moves != NULL) {
1151  move = moves->next;
1152  cuddDeallocMove(table, moves);
1153  moves = move;
1154  }
1155  return(1);
1156 
1157  ddJumpingAuxOutOfMem:
1158  while (moves != NULL) {
1159  move = moves->next;
1160  cuddDeallocMove(table, moves);
1161  moves = move;
1162  }
1163  return(0);
1164 
1165 } /* end of ddJumpingAux */
1166 
1167 
1181 static Move *
1183  DdManager * table,
1184  int x,
1185  int x_low,
1186  int initial_size)
1187 {
1188  Move *moves;
1189  Move *move;
1190  int y;
1191  int size;
1192  int limit_size = initial_size;
1193 
1194  moves = NULL;
1195  y = cuddNextLow(table,x);
1196  while (y >= x_low) {
1197  size = cuddSwapInPlace(table,y,x);
1198  if (size == 0) goto ddJumpingUpOutOfMem;
1199  move = (Move *)cuddDynamicAllocNode(table);
1200  if (move == NULL) goto ddJumpingUpOutOfMem;
1201  move->x = y;
1202  move->y = x;
1203  move->size = size;
1204  move->next = moves;
1205  moves = move;
1206  if ((double) size > table->maxGrowth * (double) limit_size) {
1207  break;
1208  } else if (size < limit_size) {
1209  limit_size = size;
1210  }
1211  x = y;
1212  y = cuddNextLow(table,x);
1213  }
1214  return(moves);
1215 
1216  ddJumpingUpOutOfMem:
1217  while (moves != NULL) {
1218  move = moves->next;
1219  cuddDeallocMove(table, moves);
1220  moves = move;
1221  }
1222  return(NULL);
1223 
1224 } /* end of ddJumpingUp */
1225 
1226 
1240 static Move *
1242  DdManager * table,
1243  int x,
1244  int x_high,
1245  int initial_size)
1246 {
1247  Move *moves;
1248  Move *move;
1249  int y;
1250  int size;
1251  int limit_size = initial_size;
1252 
1253  moves = NULL;
1254  y = cuddNextHigh(table,x);
1255  while (y <= x_high) {
1256  size = cuddSwapInPlace(table,x,y);
1257  if (size == 0) goto ddJumpingDownOutOfMem;
1258  move = (Move *)cuddDynamicAllocNode(table);
1259  if (move == NULL) goto ddJumpingDownOutOfMem;
1260  move->x = x;
1261  move->y = y;
1262  move->size = size;
1263  move->next = moves;
1264  moves = move;
1265  if ((double) size > table->maxGrowth * (double) limit_size) {
1266  break;
1267  } else if (size < limit_size) {
1268  limit_size = size;
1269  }
1270  x = y;
1271  y = cuddNextHigh(table,x);
1272  }
1273  return(moves);
1274 
1275  ddJumpingDownOutOfMem:
1276  while (moves != NULL) {
1277  move = moves->next;
1278  cuddDeallocMove(table, moves);
1279  moves = move;
1280  }
1281  return(NULL);
1282 
1283 } /* end of ddJumpingDown */
1284 
1285 
1300 static int
1302  DdManager * table,
1303  Move * moves,
1304  int size,
1305  double temp)
1306 {
1307  Move *move;
1308  int res;
1309  int best_size = size;
1310  double coin, threshold;
1311 
1312  /* Look for best size during the last sifting */
1313  for (move = moves; move != NULL; move = move->next) {
1314  if (move->size < best_size) {
1315  best_size = move->size;
1316  }
1317  }
1318 
1319  /* If best_size equals size, the last sifting did not produce any
1320  ** improvement. We now toss a coin to decide whether to retain
1321  ** this change or not.
1322  */
1323  if (best_size == size) {
1324  coin = random_generator();
1325 #ifdef DD_STATS
1326  tosses++;
1327 #endif
1328  threshold = exp(-((double)(table->keys - table->isolated - size))/temp);
1329  if (coin < threshold) {
1330 #ifdef DD_STATS
1331  acceptances++;
1332 #endif
1333  return(1);
1334  }
1335  }
1336 
1337  /* Either there was improvement, or we have decided not to
1338  ** accept the uphill move. Go to best position.
1339  */
1340  res = table->keys - table->isolated;
1341  for (move = moves; move != NULL; move = move->next) {
1342  if (res == best_size) return(1);
1343  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1344  if (!res) return(0);
1345  }
1346 
1347  return(1);
1348 
1349 } /* end of sift_backward_prob */
1350 
1351 
1364 static void
1366  DdManager * table,
1367  int * array,
1368  int lower,
1369  int upper)
1370 {
1371  int i;
1372  int nvars;
1373 
1374  nvars = upper - lower + 1;
1375  for (i = 0; i < nvars; i++) {
1376  array[i] = table->invperm[i+lower];
1377  }
1378 
1379 } /* end of copyOrder */
1380 
1381 
1394 static int
1396  DdManager * table,
1397  int * array,
1398  int lower,
1399  int upper)
1400 {
1401  int i, x, y, size;
1402  int nvars = upper - lower + 1;
1403 
1404  for (i = 0; i < nvars; i++) {
1405  x = table->perm[array[i]];
1406 #ifdef DD_DEBUG
1407  assert(x >= lower && x <= upper);
1408 #endif
1409  y = cuddNextLow(table,x);
1410  while (y >= i + lower) {
1411  size = cuddSwapInPlace(table,y,x);
1412  if (size == 0) return(0);
1413  x = y;
1414  y = cuddNextLow(table,x);
1415  }
1416  }
1417 
1418  return(1);
1419 
1420 } /* end of restoreOrder */
1421 
1634 /*---------------------------------------------------------------------------*/
1635 /* Constant declarations */
1636 /*---------------------------------------------------------------------------*/
1637 
1638 /*---------------------------------------------------------------------------*/
1639 /* Stucture declarations */
1640 /*---------------------------------------------------------------------------*/
1641 
1642 /*---------------------------------------------------------------------------*/
1643 /* Type declarations */
1644 /*---------------------------------------------------------------------------*/
1645 
1646 /*---------------------------------------------------------------------------*/
1647 /* Variable declarations */
1648 /*---------------------------------------------------------------------------*/
1649 
1650 //#ifndef lint
1651 //static char rcsid[] DD_UNUSED = "$Id: cuddAPI.c,v 1.64 2012/02/05 01:07:18 fabio Exp $";
1652 //#endif
1653 
1654 /*---------------------------------------------------------------------------*/
1655 /* Macro declarations */
1656 /*---------------------------------------------------------------------------*/
1657 
1660 /*---------------------------------------------------------------------------*/
1661 /* Static function prototypes */
1662 /*---------------------------------------------------------------------------*/
1663 
1664 static void fixVarTree (MtrNode *treenode, int *perm, int size);
1665 static int addMultiplicityGroups (DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask);
1666 
1684 DdNode *
1686  DdManager * dd,
1687  int i)
1688 {
1689  DdNode *res;
1690 
1691  if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL);
1692  if (i < dd->size) {
1693  res = dd->vars[i];
1694  } else {
1695  res = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
1696  }
1697 
1698  return(res);
1699 
1700 } /* end of Cudd_bddIthVar */
1701 
1702 
1715 DdNode *
1717  DdManager * dd)
1718 {
1719  return(dd->one);
1720 
1721 } /* end of Cudd_ReadOne */
1722 
1723 
1737 DdNode *
1739  DdManager * dd)
1740 {
1741  return(Cudd_Not(DD_ONE(dd)));
1742 
1743 } /* end of Cudd_ReadLogicZero */
1744 
1745 
1746 
1762 void
1764  DdManager * dd,
1765  unsigned int hr)
1766 {
1767  /* Internally, the package manipulates the ratio of hits to
1768  ** misses instead of the ratio of hits to accesses. */
1769  dd->minHit = (double) hr / (100.0 - (double) hr);
1770 
1771 } /* end of Cudd_SetMinHit */
1772 
1773 
1774 
1786 int
1788  DdManager * dd)
1789 {
1790  return(dd->size);
1791 
1792 } /* end of Cudd_ReadSize */
1793 
1794 
1806 void
1808  DdManager * dd)
1809 {
1810  if (dd->tree != NULL) {
1811  Mtr_FreeTree(dd->tree);
1812  dd->tree = NULL;
1813  }
1814  return;
1815 
1816 } /* end of Cudd_FreeTree */
1817 
1818 
1830 void
1832  DdManager * dd)
1833 {
1834  if (dd->treeZ != NULL) {
1835  Mtr_FreeTree(dd->treeZ);
1836  dd->treeZ = NULL;
1837  }
1838  return;
1839 
1840 } /* end of Cudd_FreeZddTree */
1841 
1842 
1858 int
1860  DdManager * dd,
1861  int i)
1862 {
1863  if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
1864  if (i < 0 || i >= dd->size) return(-1);
1865  return(dd->perm[i]);
1866 
1867 } /* end of Cudd_ReadPerm */
1868 
1869 
1884  DdManager * dd)
1885 {
1886  return(dd->epsilon);
1887 
1888 } /* end of Cudd_ReadEpsilon */
1889 
1890 
1903 void
1905  DdManager * dd,
1906  CUDD_VALUE_TYPE ep)
1907 {
1908  dd->epsilon = ep;
1909 
1910 } /* end of Cudd_SetEpsilon */
1911 
1912 
1924 unsigned long
1926  DdManager * dd)
1927 {
1928  return(dd->memused);
1929 
1930 } /* end of Cudd_ReadMemoryInUse */
1931 
1932 
1947 long
1949  DdManager * dd)
1950 {
1951  long count;
1952  int i;
1953 
1954 #ifndef DD_NO_DEATH_ROW
1955  cuddClearDeathRow(dd);
1956 #endif
1957 
1958  count = (long) (dd->keys - dd->dead);
1959 
1960  /* Count isolated projection functions. Their number is subtracted
1961  ** from the node count because they are not part of the BDDs.
1962  */
1963  for (i=0; i < dd->size; i++) {
1964  if (dd->vars[i]->ref == 1) count--;
1965  }
1966  /* Subtract from the count the unused constants. */
1967  if (DD_ZERO(dd)->ref == 1) count--;
1968  if (DD_PLUS_INFINITY(dd)->ref == 1) count--;
1969  if (DD_MINUS_INFINITY(dd)->ref == 1) count--;
1970 
1971  return(count);
1972 
1973 } /* end of Cudd_ReadNodeCount */
1974 
1975 
1976 
1990 int
1992  DdManager * dd,
1993  DD_HFP f,
1994  Cudd_HookType where)
1995 {
1996  DdHook **hook, *nextHook;
1997 
1998  switch (where) {
1999  case CUDD_PRE_GC_HOOK:
2000  hook = &(dd->preGCHook);
2001  break;
2002  case CUDD_POST_GC_HOOK:
2003  hook = &(dd->postGCHook);
2004  break;
2006  hook = &(dd->preReorderingHook);
2007  break;
2009  hook = &(dd->postReorderingHook);
2010  break;
2011  default:
2012  return(0);
2013  }
2014  nextHook = *hook;
2015  while (nextHook != NULL) {
2016  if (nextHook->f == f) {
2017  *hook = nextHook->next;
2018  FREE(nextHook);
2019  return(1);
2020  }
2021  hook = &(nextHook->next);
2022  nextHook = nextHook->next;
2023  }
2024 
2025  return(0);
2026 
2027 } /* end of Cudd_RemoveHook */
2028 
2029 
2043 int
2045  DdManager *dd,
2046  int index)
2047 {
2048  if (index >= dd->size || index < 0) return -1;
2049  return dd->subtables[dd->perm[index]].pairIndex;
2050 
2051 } /* end of Cudd_bddReadPairIndex */
2052 
2053 
2066 int
2068  DdManager *dd,
2069  int index)
2070 {
2071  if (index >= dd->size || index < 0) return(-1);
2072  if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP)
2073  return(0);
2074  else
2075  return(dd->subtables[dd->perm[index]].varToBeGrouped);
2076 
2077 } /* end of Cudd_bddIsVarToBeGrouped */
2078 
2079 
2080 
2095 int
2097  DdManager *dd,
2098  int index)
2099 {
2100  if (index >= dd->size || index < 0) return(-1);
2101  return dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP;
2102 
2103 } /* end of Cudd_bddIsVarToBeGrouped */
2104 
2105 /*---------------------------------------------------------------------------*/
2106 /* Definition of internal functions */
2107 /*---------------------------------------------------------------------------*/
2108 
2109 /*---------------------------------------------------------------------------*/
2110 /* Definition of static functions */
2111 /*---------------------------------------------------------------------------*/
2112 
2113 
2125 static void
2127  MtrNode * treenode,
2128  int * perm,
2129  int size)
2130 {
2131  treenode->index = treenode->low;
2132  treenode->low = ((int) treenode->index < size) ?
2133  perm[treenode->index] : treenode->index;
2134  if (treenode->child != NULL)
2135  fixVarTree(treenode->child, perm, size);
2136  if (treenode->younger != NULL)
2137  fixVarTree(treenode->younger, perm, size);
2138  return;
2139 
2140 } /* end of fixVarTree */
2141 
2142 
2168 static int
2170  DdManager *dd /* manager */,
2171  MtrNode *treenode /* current tree node */,
2172  int multiplicity /* how many ZDD vars per BDD var */,
2173  char *vmask /* variable pairs for which a group has been already built */,
2174  char *lmask /* levels for which a group has already been built*/)
2175 {
2176  int startV, stopV, startL;
2177  int i, j;
2178  MtrNode *auxnode = treenode;
2179 
2180  while (auxnode != NULL) {
2181  if (auxnode->child != NULL) {
2182  addMultiplicityGroups(dd,auxnode->child,multiplicity,vmask,lmask);
2183  }
2184  /* Build remaining groups. */
2185  startV = dd->permZ[auxnode->index] / multiplicity;
2186  startL = auxnode->low / multiplicity;
2187  stopV = startV + auxnode->size / multiplicity;
2188  /* Walk down vmask starting at startV and build missing groups. */
2189  for (i = startV, j = startL; i < stopV; i++) {
2190  if (vmask[i] == 0) {
2191  MtrNode *node;
2192  while (lmask[j] == 1) j++;
2193  node = Mtr_MakeGroup(auxnode, j * multiplicity, multiplicity,
2194  MTR_FIXED);
2195  if (node == NULL) {
2196  return(0);
2197  }
2198  node->index = dd->invpermZ[i * multiplicity];
2199  vmask[i] = 1;
2200  lmask[j] = 1;
2201  }
2202  }
2203  auxnode = auxnode->younger;
2204  }
2205  return(1);
2206 
2207 } /* end of addMultiplicityGroups */
2208 
2274 /*---------------------------------------------------------------------------*/
2275 /* Constant declarations */
2276 /*---------------------------------------------------------------------------*/
2277 
2278 
2279 /*---------------------------------------------------------------------------*/
2280 /* Stucture declarations */
2281 /*---------------------------------------------------------------------------*/
2282 
2283 
2284 /*---------------------------------------------------------------------------*/
2285 /* Type declarations */
2286 /*---------------------------------------------------------------------------*/
2287 
2288 
2289 /*---------------------------------------------------------------------------*/
2290 /* Variable declarations */
2291 /*---------------------------------------------------------------------------*/
2292 
2293 //#ifndef lint
2294 //static char rcsid[] DD_UNUSED = "$Id: cuddBddAbs.c,v 1.28 2012/02/05 01:07:18 fabio Exp $";
2295 //#endif
2296 
2297 /*---------------------------------------------------------------------------*/
2298 /* Macro declarations */
2299 /*---------------------------------------------------------------------------*/
2300 
2301 
2304 /*---------------------------------------------------------------------------*/
2305 /* Static function prototypes */
2306 /*---------------------------------------------------------------------------*/
2307 
2308 static int bddCheckPositiveCube (DdManager *manager, DdNode *cube);
2309 
2313 /*---------------------------------------------------------------------------*/
2314 /* Definition of exported functions */
2315 /*---------------------------------------------------------------------------*/
2316 
2317 
2330 DdNode *
2332  DdManager * manager,
2333  DdNode * f,
2334  DdNode * cube)
2335 {
2336  DdNode *res;
2337 
2338  if (bddCheckPositiveCube(manager, cube) == 0) {
2339  (void) fprintf(manager->err,
2340  "Error: Can only abstract positive cubes\n");
2341  manager->errorCode = CUDD_INVALID_ARG;
2342  return(NULL);
2343  }
2344 
2345  do {
2346  manager->reordered = 0;
2347  res = cuddBddExistAbstractRecur(manager, f, cube);
2348  } while (manager->reordered == 1);
2349 
2350  return(res);
2351 
2352 } /* end of Cudd_bddExistAbstract */
2353 
2368 int
2370  DdManager *dd, /* manager */
2371  DdNode *f, /* function */
2372  DdNode *var /* variable */)
2373 {
2374  DdNode *F, *res, *zero, *ft, *fe;
2375  unsigned topf, level;
2376  DD_CTFP cacheOp;
2377  int retval;
2378 
2379  zero = Cudd_Not(DD_ONE(dd));
2380  if (Cudd_IsConstant(f)) return(f == zero);
2381 
2382  /* From now on f is not constant. */
2383  F = Cudd_Regular(f);
2384  topf = (unsigned) dd->perm[F->index];
2385  level = (unsigned) dd->perm[var->index];
2386 
2387  /* Check terminal case. If topf > index of var, f does not depend on var.
2388  ** Therefore, var is not dependent in f. */
2389  if (topf > level) {
2390  return(0);
2391  }
2392 
2393  cacheOp = (DD_CTFP) Cudd_bddVarIsDependent;
2394  res = cuddCacheLookup2(dd,cacheOp,f,var);
2395  if (res != NULL) {
2396  return(res != zero);
2397  }
2398 
2399  /* Compute cofactors. */
2400  ft = Cudd_NotCond(cuddT(F), f != F);
2401  fe = Cudd_NotCond(cuddE(F), f != F);
2402 
2403  if (topf == level) {
2404  retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe));
2405  } else {
2406  retval = Cudd_bddVarIsDependent(dd,ft,var) &&
2407  Cudd_bddVarIsDependent(dd,fe,var);
2408  }
2409 
2410  cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval));
2411 
2412  return(retval);
2413 
2414 } /* Cudd_bddVarIsDependent */
2415 
2416 
2417 /*---------------------------------------------------------------------------*/
2418 /* Definition of internal functions */
2419 /*---------------------------------------------------------------------------*/
2420 
2421 
2436 DdNode *
2438  DdManager * manager,
2439  DdNode * f,
2440  DdNode * cube)
2441 {
2442  DdNode *F, *T, *E, *res, *res1, *res2, *one;
2443 
2444  statLine(manager);
2445  one = DD_ONE(manager);
2446  F = Cudd_Regular(f);
2447 
2448  /* Cube is guaranteed to be a cube at this point. */
2449  if (cube == one || F == one) {
2450  return(f);
2451  }
2452  /* From now on, f and cube are non-constant. */
2453 
2454  /* Abstract a variable that does not appear in f. */
2455  while (manager->perm[F->index] > manager->perm[cube->index]) {
2456  cube = cuddT(cube);
2457  if (cube == one) return(f);
2458  }
2459 
2460  /* Check the cache. */
2461  if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) {
2462  return(res);
2463  }
2464 
2465  /* Compute the cofactors of f. */
2466  T = cuddT(F); E = cuddE(F);
2467  if (f != F) {
2468  T = Cudd_Not(T); E = Cudd_Not(E);
2469  }
2470 
2471  /* If the two indices are the same, so are their levels. */
2472  if (F->index == cube->index) {
2473  if (T == one || E == one || T == Cudd_Not(E)) {
2474  return(one);
2475  }
2476  res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube));
2477  if (res1 == NULL) return(NULL);
2478  if (res1 == one) {
2479  if (F->ref != 1)
2480  cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one);
2481  return(one);
2482  }
2483  cuddRef(res1);
2484  res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube));
2485  if (res2 == NULL) {
2486  Cudd_IterDerefBdd(manager,res1);
2487  return(NULL);
2488  }
2489  cuddRef(res2);
2490  res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2));
2491  if (res == NULL) {
2492  Cudd_IterDerefBdd(manager, res1);
2493  Cudd_IterDerefBdd(manager, res2);
2494  return(NULL);
2495  }
2496  res = Cudd_Not(res);
2497  cuddRef(res);
2498  Cudd_IterDerefBdd(manager, res1);
2499  Cudd_IterDerefBdd(manager, res2);
2500  if (F->ref != 1)
2501  cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
2502  cuddDeref(res);
2503  return(res);
2504  } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */
2505  res1 = cuddBddExistAbstractRecur(manager, T, cube);
2506  if (res1 == NULL) return(NULL);
2507  cuddRef(res1);
2508  res2 = cuddBddExistAbstractRecur(manager, E, cube);
2509  if (res2 == NULL) {
2510  Cudd_IterDerefBdd(manager, res1);
2511  return(NULL);
2512  }
2513  cuddRef(res2);
2514  /* ITE takes care of possible complementation of res1 and of the
2515  ** case in which res1 == res2. */
2516  res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2);
2517  if (res == NULL) {
2518  Cudd_IterDerefBdd(manager, res1);
2519  Cudd_IterDerefBdd(manager, res2);
2520  return(NULL);
2521  }
2522  cuddDeref(res1);
2523  cuddDeref(res2);
2524  if (F->ref != 1)
2525  cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
2526  return(res);
2527  }
2528 
2529 } /* end of cuddBddExistAbstractRecur */
2530 
2531 
2546 DdNode *
2548  DdManager * manager,
2549  DdNode * f,
2550  DdNode * g,
2551  DdNode * cube)
2552 {
2553  DdNode *F, *fv, *fnv, *G, *gv, *gnv;
2554  DdNode *one, *zero, *r, *t, *e, *Cube;
2555  unsigned int topf, topg, topcube, top, index;
2556 
2557  statLine(manager);
2558  one = DD_ONE(manager);
2559  zero = Cudd_Not(one);
2560 
2561  /* Terminal cases. */
2562  if (f == g) {
2563  return(zero);
2564  }
2565  if (f == Cudd_Not(g)) {
2566  return(one);
2567  }
2568  if (cube == one) {
2569  return(cuddBddXorRecur(manager, f, g));
2570  }
2571  if (f == one) {
2572  return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube));
2573  }
2574  if (g == one) {
2575  return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube));
2576  }
2577  if (f == zero) {
2578  return(cuddBddExistAbstractRecur(manager, g, cube));
2579  }
2580  if (g == zero) {
2581  return(cuddBddExistAbstractRecur(manager, f, cube));
2582  }
2583 
2584  /* At this point f, g, and cube are not constant. */
2585 
2586  if (f > g) { /* Try to increase cache efficiency. */
2587  DdNode *tmp = f;
2588  f = g;
2589  g = tmp;
2590  }
2591 
2592  /* Check cache. */
2593  r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube);
2594  if (r != NULL) {
2595  return(r);
2596  }
2597 
2598  /* Here we can skip the use of cuddI, because the operands are known
2599  ** to be non-constant.
2600  */
2601  F = Cudd_Regular(f);
2602  topf = manager->perm[F->index];
2603  G = Cudd_Regular(g);
2604  topg = manager->perm[G->index];
2605  top = ddMin(topf, topg);
2606  topcube = manager->perm[cube->index];
2607 
2608  if (topcube < top) {
2609  return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube)));
2610  }
2611  /* Now, topcube >= top. */
2612 
2613  if (topf == top) {
2614  index = F->index;
2615  fv = cuddT(F);
2616  fnv = cuddE(F);
2617  if (Cudd_IsComplement(f)) {
2618  fv = Cudd_Not(fv);
2619  fnv = Cudd_Not(fnv);
2620  }
2621  } else {
2622  index = G->index;
2623  fv = fnv = f;
2624  }
2625 
2626  if (topg == top) {
2627  gv = cuddT(G);
2628  gnv = cuddE(G);
2629  if (Cudd_IsComplement(g)) {
2630  gv = Cudd_Not(gv);
2631  gnv = Cudd_Not(gnv);
2632  }
2633  } else {
2634  gv = gnv = g;
2635  }
2636 
2637  if (topcube == top) {
2638  Cube = cuddT(cube);
2639  } else {
2640  Cube = cube;
2641  }
2642 
2643  t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube);
2644  if (t == NULL) return(NULL);
2645 
2646  /* Special case: 1 OR anything = 1. Hence, no need to compute
2647  ** the else branch if t is 1.
2648  */
2649  if (t == one && topcube == top) {
2650  cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one);
2651  return(one);
2652  }
2653  cuddRef(t);
2654 
2655  e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube);
2656  if (e == NULL) {
2657  Cudd_IterDerefBdd(manager, t);
2658  return(NULL);
2659  }
2660  cuddRef(e);
2661 
2662  if (topcube == top) { /* abstract */
2663  r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
2664  if (r == NULL) {
2665  Cudd_IterDerefBdd(manager, t);
2666  Cudd_IterDerefBdd(manager, e);
2667  return(NULL);
2668  }
2669  r = Cudd_Not(r);
2670  cuddRef(r);
2671  Cudd_IterDerefBdd(manager, t);
2672  Cudd_IterDerefBdd(manager, e);
2673  cuddDeref(r);
2674  } else if (t == e) {
2675  r = t;
2676  cuddDeref(t);
2677  cuddDeref(e);
2678  } else {
2679  if (Cudd_IsComplement(t)) {
2680  r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
2681  if (r == NULL) {
2682  Cudd_IterDerefBdd(manager, t);
2683  Cudd_IterDerefBdd(manager, e);
2684  return(NULL);
2685  }
2686  r = Cudd_Not(r);
2687  } else {
2688  r = cuddUniqueInter(manager,(int)index,t,e);
2689  if (r == NULL) {
2690  Cudd_IterDerefBdd(manager, t);
2691  Cudd_IterDerefBdd(manager, e);
2692  return(NULL);
2693  }
2694  }
2695  cuddDeref(e);
2696  cuddDeref(t);
2697  }
2698  cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r);
2699  return (r);
2700 
2701 } /* end of cuddBddXorExistAbstractRecur */
2702 
2703 
2718 DdNode *
2720  DdManager * manager,
2721  DdNode * f,
2722  DdNode * var)
2723 {
2724  DdNode *T, *E, *res, *res1, *res2;
2725 
2726  statLine(manager);
2727  if (cuddI(manager,f->index) > manager->perm[var->index]) {
2728  /* f does not depend on var. */
2729  return(Cudd_Not(DD_ONE(manager)));
2730  }
2731 
2732  /* From now on, f is non-constant. */
2733 
2734  /* If the two indices are the same, so are their levels. */
2735  if (f->index == var->index) {
2736  res = cuddBddXorRecur(manager, cuddT(f), cuddE(f));
2737  return(res);
2738  }
2739 
2740  /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */
2741 
2742  /* Check the cache. */
2743  res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var);
2744  if (res != NULL) {
2745  return(res);
2746  }
2747 
2748  /* Compute the cofactors of f. */
2749  T = cuddT(f); E = cuddE(f);
2750 
2751  res1 = cuddBddBooleanDiffRecur(manager, T, var);
2752  if (res1 == NULL) return(NULL);
2753  cuddRef(res1);
2754  res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var);
2755  if (res2 == NULL) {
2756  Cudd_IterDerefBdd(manager, res1);
2757  return(NULL);
2758  }
2759  cuddRef(res2);
2760  /* ITE takes care of possible complementation of res1 and of the
2761  ** case in which res1 == res2. */
2762  res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2);
2763  if (res == NULL) {
2764  Cudd_IterDerefBdd(manager, res1);
2765  Cudd_IterDerefBdd(manager, res2);
2766  return(NULL);
2767  }
2768  cuddDeref(res1);
2769  cuddDeref(res2);
2770  cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res);
2771  return(res);
2772 
2773 } /* end of cuddBddBooleanDiffRecur */
2774 
2775 
2776 /*---------------------------------------------------------------------------*/
2777 /* Definition of static functions */
2778 /*---------------------------------------------------------------------------*/
2779 
2790 static int
2792  DdManager * manager,
2793  DdNode * cube)
2794 {
2795  if (Cudd_IsComplement(cube)) return(0);
2796  if (cube == DD_ONE(manager)) return(1);
2797  if (cuddIsConstant(cube)) return(0);
2798  if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) {
2799  return(bddCheckPositiveCube(manager, cuddT(cube)));
2800  }
2801  return(0);
2802 
2803 } /* end of bddCheckPositiveCube */
2804 
2882 /*---------------------------------------------------------------------------*/
2883 /* Constant declarations */
2884 /*---------------------------------------------------------------------------*/
2885 
2886 
2887 /*---------------------------------------------------------------------------*/
2888 /* Stucture declarations */
2889 /*---------------------------------------------------------------------------*/
2890 
2891 
2892 /*---------------------------------------------------------------------------*/
2893 /* Type declarations */
2894 /*---------------------------------------------------------------------------*/
2895 
2896 
2897 /*---------------------------------------------------------------------------*/
2898 /* Variable declarations */
2899 /*---------------------------------------------------------------------------*/
2900 
2901 //#ifndef lint
2902 //static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.26 2012/02/05 01:07:18 fabio Exp $";
2903 //#endif
2904 
2905 /*---------------------------------------------------------------------------*/
2906 /* Macro declarations */
2907 /*---------------------------------------------------------------------------*/
2908 
2909 
2912 /*---------------------------------------------------------------------------*/
2913 /* Static function prototypes */
2914 /*---------------------------------------------------------------------------*/
2915 
2916 static void bddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one);
2917 static int bddVarToCanonical (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
2918 static int bddVarToCanonicalSimple (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
2919 
2923 /*---------------------------------------------------------------------------*/
2924 /* Definition of exported functions */
2925 /*---------------------------------------------------------------------------*/
2926 
2927 
2941 DdNode *
2943  DdManager * dd,
2944  DdNode * f,
2945  DdNode * g,
2946  DdNode * h)
2947 {
2948  DdNode *res;
2949 
2950  do {
2951  dd->reordered = 0;
2952  res = cuddBddIteRecur(dd,f,g,h);
2953  } while (dd->reordered == 1);
2954  return(res);
2955 
2956 } /* end of Cudd_bddIte */
2957 
2958 
2959 
2973 DdNode *
2975  DdManager * dd,
2976  DdNode * f,
2977  DdNode * g,
2978  DdNode * h)
2979 {
2980  DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
2981  DdNode *one = DD_ONE(dd);
2982  DdNode *zero = Cudd_Not(one);
2983  int comple;
2984  unsigned int topf, topg, toph, v;
2985 
2986  statLine(dd);
2987  /* Trivial cases. */
2988  if (f == one) /* ITE(1,G,H) => G */
2989  return(g);
2990 
2991  if (f == zero) /* ITE(0,G,H) => H */
2992  return(h);
2993 
2994  /* f now not a constant. */
2995  bddVarToConst(f, &g, &h, one); /* possibly convert g or h */
2996  /* to constants */
2997 
2998  if (g == h) /* ITE(F,G,G) => G */
2999  return(g);
3000 
3001  if (Cudd_IsConstant(g) && Cudd_IsConstant(h))
3002  return(DD_NON_CONSTANT); /* ITE(F,1,0) or ITE(F,0,1) */
3003  /* => DD_NON_CONSTANT */
3004 
3005  if (g == Cudd_Not(h))
3006  return(DD_NON_CONSTANT); /* ITE(F,G,G') => DD_NON_CONSTANT */
3007  /* if F != G and F != G' */
3008 
3009  comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph);
3010 
3011  /* Cache lookup. */
3012  r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h);
3013  if (r != NULL) {
3014  return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT));
3015  }
3016 
3017  v = ddMin(topg, toph);
3018 
3019  /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */
3020  if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
3021  return(DD_NON_CONSTANT);
3022  }
3023 
3024  /* Compute cofactors. */
3025  if (topf <= v) {
3026  v = ddMin(topf, v); /* v = top_var(F,G,H) */
3027  Fv = cuddT(f); Fnv = cuddE(f);
3028  } else {
3029  Fv = Fnv = f;
3030  }
3031 
3032  if (topg == v) {
3033  Gv = cuddT(g); Gnv = cuddE(g);
3034  } else {
3035  Gv = Gnv = g;
3036  }
3037 
3038  if (toph == v) {
3039  H = Cudd_Regular(h);
3040  Hv = cuddT(H); Hnv = cuddE(H);
3041  if (Cudd_IsComplement(h)) {
3042  Hv = Cudd_Not(Hv);
3043  Hnv = Cudd_Not(Hnv);
3044  }
3045  } else {
3046  Hv = Hnv = h;
3047  }
3048 
3049  /* Recursion. */
3050  t = Cudd_bddIteConstant(dd, Fv, Gv, Hv);
3051  if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) {
3053  return(DD_NON_CONSTANT);
3054  }
3055  e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv);
3056  if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) {
3058  return(DD_NON_CONSTANT);
3059  }
3060  cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t);
3061  return(Cudd_NotCond(t,comple));
3062 
3063 } /* end of Cudd_bddIteConstant */
3064 
3065 
3081 DdNode *
3083  DdManager * dd /* manager */,
3084  DdNode * f /* first operand */,
3085  DdNode * g /* second operand */)
3086 {
3087  DdNode *res;
3088 
3089  do {
3090  dd->reordered = 0;
3091  res = cuddBddIntersectRecur(dd,f,g);
3092  } while (dd->reordered == 1);
3093 
3094  return(res);
3095 
3096 } /* end of Cudd_bddIntersect */
3097 
3098 
3113 DdNode *
3115  DdManager * dd,
3116  DdNode * f,
3117  DdNode * g)
3118 {
3119  DdNode *res;
3120 
3121  do {
3122  dd->reordered = 0;
3123  res = cuddBddAndRecur(dd,f,g);
3124  } while (dd->reordered == 1);
3125  return(res);
3126 
3127 } /* end of Cudd_bddAnd */
3128 
3129 
3145 DdNode *
3147  DdManager * dd,
3148  DdNode * f,
3149  DdNode * g,
3150  unsigned int limit)
3151 {
3152  DdNode *res;
3153  unsigned int saveLimit = dd->maxLive;
3154 
3155  dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
3156  do {
3157  dd->reordered = 0;
3158  res = cuddBddAndRecur(dd,f,g);
3159  } while (dd->reordered == 1);
3160  dd->maxLive = saveLimit;
3161  return(res);
3162 
3163 } /* end of Cudd_bddAndLimit */
3164 
3165 
3180 DdNode *
3182  DdManager * dd,
3183  DdNode * f,
3184  DdNode * g)
3185 {
3186  DdNode *res;
3187 
3188  do {
3189  dd->reordered = 0;
3190  res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
3191  } while (dd->reordered == 1);
3192  res = Cudd_NotCond(res,res != NULL);
3193  return(res);
3194 
3195 } /* end of Cudd_bddOr */
3196 
3197 
3213 DdNode *
3215  DdManager * dd,
3216  DdNode * f,
3217  DdNode * g,
3218  unsigned int limit)
3219 {
3220  DdNode *res;
3221  unsigned int saveLimit = dd->maxLive;
3222 
3223  dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
3224  do {
3225  dd->reordered = 0;
3226  res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
3227  } while (dd->reordered == 1);
3228  dd->maxLive = saveLimit;
3229  res = Cudd_NotCond(res,res != NULL);
3230  return(res);
3231 
3232 } /* end of Cudd_bddOrLimit */
3233 
3234 
3235 /* end of Cudd_bddNand */
3236 
3237 
3252 DdNode *
3254  DdManager * dd,
3255  DdNode * f,
3256  DdNode * g)
3257 {
3258  DdNode *res;
3259 
3260  do {
3261  dd->reordered = 0;
3262  res = cuddBddXorRecur(dd,f,g);
3263  } while (dd->reordered == 1);
3264  return(res);
3265 
3266 } /* end of Cudd_bddXor */
3267 
3268 
3269 
3282 int
3284  DdManager * dd,
3285  DdNode * f,
3286  DdNode * g)
3287 {
3288  DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn;
3289  unsigned int topf, topg, res;
3290 
3291  statLine(dd);
3292  /* Terminal cases and normalization. */
3293  if (f == g) return(1);
3294 
3295  if (Cudd_IsComplement(g)) {
3296  /* Special case: if f is regular and g is complemented,
3297  ** f(1,...,1) = 1 > 0 = g(1,...,1).
3298  */
3299  if (!Cudd_IsComplement(f)) return(0);
3300  /* Both are complemented: Swap and complement because
3301  ** f <= g <=> g' <= f' and we want the second argument to be regular.
3302  */
3303  tmp = g;
3304  g = Cudd_Not(f);
3305  f = Cudd_Not(tmp);
3306  } else if (Cudd_IsComplement(f) && g < f) {
3307  tmp = g;
3308  g = Cudd_Not(f);
3309  f = Cudd_Not(tmp);
3310  }
3311 
3312  /* Now g is regular and, if f is not regular, f < g. */
3313  one = DD_ONE(dd);
3314  if (g == one) return(1); /* no need to test against zero */
3315  if (f == one) return(0); /* since at this point g != one */
3316  if (Cudd_Not(f) == g) return(0); /* because neither is constant */
3317  zero = Cudd_Not(one);
3318  if (f == zero) return(1);
3319 
3320  /* Here neither f nor g is constant. */
3321 
3322  /* Check cache. */
3323  tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_bddLeq,f,g);
3324  if (tmp != NULL) {
3325  return(tmp == one);
3326  }
3327 
3328  /* Compute cofactors. */
3329  F = Cudd_Regular(f);
3330  topf = dd->perm[F->index];
3331  topg = dd->perm[g->index];
3332  if (topf <= topg) {
3333  fv = cuddT(F); fvn = cuddE(F);
3334  if (f != F) {
3335  fv = Cudd_Not(fv);
3336  fvn = Cudd_Not(fvn);
3337  }
3338  } else {
3339  fv = fvn = f;
3340  }
3341  if (topg <= topf) {
3342  gv = cuddT(g); gvn = cuddE(g);
3343  } else {
3344  gv = gvn = g;
3345  }
3346 
3347  /* Recursive calls. Since we want to maximize the probability of
3348  ** the special case f(1,...,1) > g(1,...,1), we consider the negative
3349  ** cofactors first. Indeed, the complementation parity of the positive
3350  ** cofactors is the same as the one of the parent functions.
3351  */
3352  res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv);
3353 
3354  /* Store result in cache and return. */
3355  cuddCacheInsert2(dd,(DD_CTFP)Cudd_bddLeq,f,g,(res ? one : zero));
3356  return(res);
3357 
3358 } /* end of Cudd_bddLeq */
3359 
3360 
3361 /*---------------------------------------------------------------------------*/
3362 /* Definition of internal functions */
3363 /*---------------------------------------------------------------------------*/
3364 
3365 
3379 DdNode *
3381  DdManager * dd,
3382  DdNode * f,
3383  DdNode * g,
3384  DdNode * h)
3385 {
3386  DdNode *one, *zero, *res;
3387  DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
3388  unsigned int topf, topg, toph, v;
3389  int index;
3390  int comple;
3391 
3392  statLine(dd);
3393  /* Terminal cases. */
3394 
3395  /* One variable cases. */
3396  if (f == (one = DD_ONE(dd))) /* ITE(1,G,H) = G */
3397  return(g);
3398 
3399  if (f == (zero = Cudd_Not(one))) /* ITE(0,G,H) = H */
3400  return(h);
3401 
3402  /* From now on, f is known not to be a constant. */
3403  if (g == one || f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
3404  if (h == zero) { /* ITE(F,1,0) = F */
3405  return(f);
3406  } else {
3407  res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h));
3408  return(Cudd_NotCond(res,res != NULL));
3409  }
3410  } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
3411  if (h == one) { /* ITE(F,0,1) = !F */
3412  return(Cudd_Not(f));
3413  } else {
3414  res = cuddBddAndRecur(dd,Cudd_Not(f),h);
3415  return(res);
3416  }
3417  }
3418  if (h == zero || f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
3419  res = cuddBddAndRecur(dd,f,g);
3420  return(res);
3421  } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
3422  res = cuddBddAndRecur(dd,f,Cudd_Not(g));
3423  return(Cudd_NotCond(res,res != NULL));
3424  }
3425 
3426  /* Check remaining one variable case. */
3427  if (g == h) { /* ITE(F,G,G) = G */
3428  return(g);
3429  } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */
3430  res = cuddBddXorRecur(dd,f,h);
3431  return(res);
3432  }
3433 
3434  /* From here, there are no constants. */
3435  comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph);
3436 
3437  /* f & g are now regular pointers */
3438 
3439  v = ddMin(topg, toph);
3440 
3441  /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */
3442  if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
3443  r = cuddUniqueInter(dd, (int) f->index, g, h);
3444  return(Cudd_NotCond(r,comple && r != NULL));
3445  }
3446 
3447  /* Check cache. */
3448  r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h);
3449  if (r != NULL) {
3450  return(Cudd_NotCond(r,comple));
3451  }
3452 
3453  /* Compute cofactors. */
3454  if (topf <= v) {
3455  v = ddMin(topf, v); /* v = top_var(F,G,H) */
3456  index = f->index;
3457  Fv = cuddT(f); Fnv = cuddE(f);
3458  } else {
3459  Fv = Fnv = f;
3460  }
3461  if (topg == v) {
3462  index = g->index;
3463  Gv = cuddT(g); Gnv = cuddE(g);
3464  } else {
3465  Gv = Gnv = g;
3466  }
3467  if (toph == v) {
3468  H = Cudd_Regular(h);
3469  index = H->index;
3470  Hv = cuddT(H); Hnv = cuddE(H);
3471  if (Cudd_IsComplement(h)) {
3472  Hv = Cudd_Not(Hv);
3473  Hnv = Cudd_Not(Hnv);
3474  }
3475  } else {
3476  Hv = Hnv = h;
3477  }
3478 
3479  /* Recursive step. */
3480  t = cuddBddIteRecur(dd,Fv,Gv,Hv);
3481  if (t == NULL) return(NULL);
3482  cuddRef(t);
3483 
3484  e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv);
3485  if (e == NULL) {
3486  Cudd_IterDerefBdd(dd,t);
3487  return(NULL);
3488  }
3489  cuddRef(e);
3490 
3491  r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
3492  if (r == NULL) {
3493  Cudd_IterDerefBdd(dd,t);
3494  Cudd_IterDerefBdd(dd,e);
3495  return(NULL);
3496  }
3497  cuddDeref(t);
3498  cuddDeref(e);
3499 
3500  cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r);
3501  return(Cudd_NotCond(r,comple));
3502 
3503 } /* end of cuddBddIteRecur */
3504 
3505 
3517 DdNode *
3519  DdManager * dd,
3520  DdNode * f,
3521  DdNode * g)
3522 {
3523  DdNode *res;
3524  DdNode *F, *G, *t, *e;
3525  DdNode *fv, *fnv, *gv, *gnv;
3526  DdNode *one, *zero;
3527  unsigned int index, topf, topg;
3528 
3529  statLine(dd);
3530  one = DD_ONE(dd);
3531  zero = Cudd_Not(one);
3532 
3533  /* Terminal cases. */
3534  if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
3535  if (f == g || g == one) return(f);
3536  if (f == one) return(g);
3537 
3538  /* At this point f and g are not constant. */
3539  if (f > g) { DdNode *tmp = f; f = g; g = tmp; }
3540  res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g);
3541  if (res != NULL) return(res);
3542 
3543  /* Find splitting variable. Here we can skip the use of cuddI,
3544  ** because the operands are known to be non-constant.
3545  */
3546  F = Cudd_Regular(f);
3547  topf = dd->perm[F->index];
3548  G = Cudd_Regular(g);
3549  topg = dd->perm[G->index];
3550 
3551  /* Compute cofactors. */
3552  if (topf <= topg) {
3553  index = F->index;
3554  fv = cuddT(F);
3555  fnv = cuddE(F);
3556  if (Cudd_IsComplement(f)) {
3557  fv = Cudd_Not(fv);
3558  fnv = Cudd_Not(fnv);
3559  }
3560  } else {
3561  index = G->index;
3562  fv = fnv = f;
3563  }
3564 
3565  if (topg <= topf) {
3566  gv = cuddT(G);
3567  gnv = cuddE(G);
3568  if (Cudd_IsComplement(g)) {
3569  gv = Cudd_Not(gv);
3570  gnv = Cudd_Not(gnv);
3571  }
3572  } else {
3573  gv = gnv = g;
3574  }
3575 
3576  /* Compute partial results. */
3577  t = cuddBddIntersectRecur(dd,fv,gv);
3578  if (t == NULL) return(NULL);
3579  cuddRef(t);
3580  if (t != zero) {
3581  e = zero;
3582  } else {
3583  e = cuddBddIntersectRecur(dd,fnv,gnv);
3584  if (e == NULL) {
3585  Cudd_IterDerefBdd(dd, t);
3586  return(NULL);
3587  }
3588  }
3589  cuddRef(e);
3590 
3591  if (t == e) { /* both equal zero */
3592  res = t;
3593  } else if (Cudd_IsComplement(t)) {
3594  res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e));
3595  if (res == NULL) {
3596  Cudd_IterDerefBdd(dd, t);
3597  Cudd_IterDerefBdd(dd, e);
3598  return(NULL);
3599  }
3600  res = Cudd_Not(res);
3601  } else {
3602  res = cuddUniqueInter(dd,(int)index,t,e);
3603  if (res == NULL) {
3604  Cudd_IterDerefBdd(dd, t);
3605  Cudd_IterDerefBdd(dd, e);
3606  return(NULL);
3607  }
3608  }
3609  cuddDeref(e);
3610  cuddDeref(t);
3611 
3612  cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res);
3613 
3614  return(res);
3615 
3616 } /* end of cuddBddIntersectRecur */
3617 
3618 
3632 DdNode *
3634  DdManager * manager,
3635  DdNode * f,
3636  DdNode * g)
3637 {
3638  DdNode *F, *fv, *fnv, *G, *gv, *gnv;
3639  DdNode *one, *r, *t, *e;
3640  unsigned int topf, topg, index;
3641 
3642  statLine(manager);
3643  one = DD_ONE(manager);
3644 
3645  /* Terminal cases. */
3646  F = Cudd_Regular(f);
3647  G = Cudd_Regular(g);
3648  if (F == G) {
3649  if (f == g) return(f);
3650  else return(Cudd_Not(one));
3651  }
3652  if (F == one) {
3653  if (f == one) return(g);
3654  else return(f);
3655  }
3656  if (G == one) {
3657  if (g == one) return(f);
3658  else return(g);
3659  }
3660 
3661  /* At this point f and g are not constant. */
3662  if (f > g) { /* Try to increase cache efficiency. */
3663  DdNode *tmp = f;
3664  f = g;
3665  g = tmp;
3666  F = Cudd_Regular(f);
3667  G = Cudd_Regular(g);
3668  }
3669 
3670  /* Check cache. */
3671  if (F->ref != 1 || G->ref != 1) {
3672  r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
3673  if (r != NULL) return(r);
3674  }
3675 
3676  /* Here we can skip the use of cuddI, because the operands are known
3677  ** to be non-constant.
3678  */
3679  topf = manager->perm[F->index];
3680  topg = manager->perm[G->index];
3681 
3682  /* Compute cofactors. */
3683  if (topf <= topg) {
3684  index = F->index;
3685  fv = cuddT(F);
3686  fnv = cuddE(F);
3687  if (Cudd_IsComplement(f)) {
3688  fv = Cudd_Not(fv);
3689  fnv = Cudd_Not(fnv);
3690  }
3691  } else {
3692  index = G->index;
3693  fv = fnv = f;
3694  }
3695 
3696  if (topg <= topf) {
3697  gv = cuddT(G);
3698  gnv = cuddE(G);
3699  if (Cudd_IsComplement(g)) {
3700  gv = Cudd_Not(gv);
3701  gnv = Cudd_Not(gnv);
3702  }
3703  } else {
3704  gv = gnv = g;
3705  }
3706 
3707  t = cuddBddAndRecur(manager, fv, gv);
3708  if (t == NULL) return(NULL);
3709  cuddRef(t);
3710 
3711  e = cuddBddAndRecur(manager, fnv, gnv);
3712  if (e == NULL) {
3713  Cudd_IterDerefBdd(manager, t);
3714  return(NULL);
3715  }
3716  cuddRef(e);
3717 
3718  if (t == e) {
3719  r = t;
3720  } else {
3721  if (Cudd_IsComplement(t)) {
3722  r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
3723  if (r == NULL) {
3724  Cudd_IterDerefBdd(manager, t);
3725  Cudd_IterDerefBdd(manager, e);
3726  return(NULL);
3727  }
3728  r = Cudd_Not(r);
3729  } else {
3730  r = cuddUniqueInter(manager,(int)index,t,e);
3731  if (r == NULL) {
3732  Cudd_IterDerefBdd(manager, t);
3733  Cudd_IterDerefBdd(manager, e);
3734  return(NULL);
3735  }
3736  }
3737  }
3738  cuddDeref(e);
3739  cuddDeref(t);
3740  if (F->ref != 1 || G->ref != 1)
3741  cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
3742  return(r);
3743 
3744 } /* end of cuddBddAndRecur */
3745 
3746 
3760 DdNode *
3762  DdManager * manager,
3763  DdNode * f,
3764  DdNode * g)
3765 {
3766  DdNode *fv, *fnv, *G, *gv, *gnv;
3767  DdNode *one, *zero, *r, *t, *e;
3768  unsigned int topf, topg, index;
3769 
3770  statLine(manager);
3771  one = DD_ONE(manager);
3772  zero = Cudd_Not(one);
3773 
3774  /* Terminal cases. */
3775  if (f == g) return(zero);
3776  if (f == Cudd_Not(g)) return(one);
3777  if (f > g) { /* Try to increase cache efficiency and simplify tests. */
3778  DdNode *tmp = f;
3779  f = g;
3780  g = tmp;
3781  }
3782  if (g == zero) return(f);
3783  if (g == one) return(Cudd_Not(f));
3784  if (Cudd_IsComplement(f)) {
3785  f = Cudd_Not(f);
3786  g = Cudd_Not(g);
3787  }
3788  /* Now the first argument is regular. */
3789  if (f == one) return(Cudd_Not(g));
3790 
3791  /* At this point f and g are not constant. */
3792 
3793  /* Check cache. */
3794  r = cuddCacheLookup2(manager, Cudd_bddXor, f, g);
3795  if (r != NULL) return(r);
3796 
3797  /* Here we can skip the use of cuddI, because the operands are known
3798  ** to be non-constant.
3799  */
3800  topf = manager->perm[f->index];
3801  G = Cudd_Regular(g);
3802  topg = manager->perm[G->index];
3803 
3804  /* Compute cofactors. */
3805  if (topf <= topg) {
3806  index = f->index;
3807  fv = cuddT(f);
3808  fnv = cuddE(f);
3809  } else {
3810  index = G->index;
3811  fv = fnv = f;
3812  }
3813 
3814  if (topg <= topf) {
3815  gv = cuddT(G);
3816  gnv = cuddE(G);
3817  if (Cudd_IsComplement(g)) {
3818  gv = Cudd_Not(gv);
3819  gnv = Cudd_Not(gnv);
3820  }
3821  } else {
3822  gv = gnv = g;
3823  }
3824 
3825  t = cuddBddXorRecur(manager, fv, gv);
3826  if (t == NULL) return(NULL);
3827  cuddRef(t);
3828 
3829  e = cuddBddXorRecur(manager, fnv, gnv);
3830  if (e == NULL) {
3831  Cudd_IterDerefBdd(manager, t);
3832  return(NULL);
3833  }
3834  cuddRef(e);
3835 
3836  if (t == e) {
3837  r = t;
3838  } else {
3839  if (Cudd_IsComplement(t)) {
3840  r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
3841  if (r == NULL) {
3842  Cudd_IterDerefBdd(manager, t);
3843  Cudd_IterDerefBdd(manager, e);
3844  return(NULL);
3845  }
3846  r = Cudd_Not(r);
3847  } else {
3848  r = cuddUniqueInter(manager,(int)index,t,e);
3849  if (r == NULL) {
3850  Cudd_IterDerefBdd(manager, t);
3851  Cudd_IterDerefBdd(manager, e);
3852  return(NULL);
3853  }
3854  }
3855  }
3856  cuddDeref(e);
3857  cuddDeref(t);
3858  cuddCacheInsert2(manager, Cudd_bddXor, f, g, r);
3859  return(r);
3860 
3861 } /* end of cuddBddXorRecur */
3862 
3863 
3864 /*---------------------------------------------------------------------------*/
3865 /* Definition of static functions */
3866 /*---------------------------------------------------------------------------*/
3867 
3868 
3881 static void
3883  DdNode * f,
3884  DdNode ** gp,
3885  DdNode ** hp,
3886  DdNode * one)
3887 {
3888  DdNode *g = *gp;
3889  DdNode *h = *hp;
3890 
3891  if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
3892  *gp = one;
3893  } else if (f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
3894  *gp = Cudd_Not(one);
3895  }
3896  if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
3897  *hp = Cudd_Not(one);
3898  } else if (f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
3899  *hp = one;
3900  }
3901 
3902 } /* end of bddVarToConst */
3903 
3904 
3916 static int
3918  DdManager * dd,
3919  DdNode ** fp,
3920  DdNode ** gp,
3921  DdNode ** hp,
3922  unsigned int * topfp,
3923  unsigned int * topgp,
3924  unsigned int * tophp)
3925 {
3926  register DdNode *F, *G, *H, *r, *f, *g, *h;
3927  register unsigned int topf, topg, toph;
3928  DdNode *one = dd->one;
3929  int comple, change;
3930 
3931  f = *fp;
3932  g = *gp;
3933  h = *hp;
3934  F = Cudd_Regular(f);
3935  G = Cudd_Regular(g);
3936  H = Cudd_Regular(h);
3937  topf = cuddI(dd,F->index);
3938  topg = cuddI(dd,G->index);
3939  toph = cuddI(dd,H->index);
3940 
3941  change = 0;
3942 
3943  if (G == one) { /* ITE(F,c,H) */
3944  if ((topf > toph) || (topf == toph && f > h)) {
3945  r = h;
3946  h = f;
3947  f = r; /* ITE(F,1,H) = ITE(H,1,F) */
3948  if (g != one) { /* g == zero */
3949  f = Cudd_Not(f); /* ITE(F,0,H) = ITE(!H,0,!F) */
3950  h = Cudd_Not(h);
3951  }
3952  change = 1;
3953  }
3954  } else if (H == one) { /* ITE(F,G,c) */
3955  if ((topf > topg) || (topf == topg && f > g)) {
3956  r = g;
3957  g = f;
3958  f = r; /* ITE(F,G,0) = ITE(G,F,0) */
3959  if (h == one) {
3960  f = Cudd_Not(f); /* ITE(F,G,1) = ITE(!G,!F,1) */
3961  g = Cudd_Not(g);
3962  }
3963  change = 1;
3964  }
3965  } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = ITE(G,F,!F) */
3966  if ((topf > topg) || (topf == topg && f > g)) {
3967  r = f;
3968  f = g;
3969  g = r;
3970  h = Cudd_Not(r);
3971  change = 1;
3972  }
3973  }
3974  /* adjust pointers so that the first 2 arguments to ITE are regular */
3975  if (Cudd_IsComplement(f) != 0) { /* ITE(!F,G,H) = ITE(F,H,G) */
3976  f = Cudd_Not(f);
3977  r = g;
3978  g = h;
3979  h = r;
3980  change = 1;
3981  }
3982  comple = 0;
3983  if (Cudd_IsComplement(g) != 0) { /* ITE(F,!G,H) = !ITE(F,G,!H) */
3984  g = Cudd_Not(g);
3985  h = Cudd_Not(h);
3986  change = 1;
3987  comple = 1;
3988  }
3989  if (change != 0) {
3990  *fp = f;
3991  *gp = g;
3992  *hp = h;
3993  }
3994  *topfp = cuddI(dd,f->index);
3995  *topgp = cuddI(dd,g->index);
3996  *tophp = cuddI(dd,Cudd_Regular(h)->index);
3997 
3998  return(comple);
3999 
4000 } /* end of bddVarToCanonical */
4001 
4002 
4018 static int
4020  DdManager * dd,
4021  DdNode ** fp,
4022  DdNode ** gp,
4023  DdNode ** hp,
4024  unsigned int * topfp,
4025  unsigned int * topgp,
4026  unsigned int * tophp)
4027 {
4028  register DdNode *r, *f, *g, *h;
4029  int comple, change;
4030 
4031  f = *fp;
4032  g = *gp;
4033  h = *hp;
4034 
4035  change = 0;
4036 
4037  /* adjust pointers so that the first 2 arguments to ITE are regular */
4038  if (Cudd_IsComplement(f)) { /* ITE(!F,G,H) = ITE(F,H,G) */
4039  f = Cudd_Not(f);
4040  r = g;
4041  g = h;
4042  h = r;
4043  change = 1;
4044  }
4045  comple = 0;
4046  if (Cudd_IsComplement(g)) { /* ITE(F,!G,H) = !ITE(F,G,!H) */
4047  g = Cudd_Not(g);
4048  h = Cudd_Not(h);
4049  change = 1;
4050  comple = 1;
4051  }
4052  if (change) {
4053  *fp = f;
4054  *gp = g;
4055  *hp = h;
4056  }
4057 
4058  /* Here we can skip the use of cuddI, because the operands are known
4059  ** to be non-constant.
4060  */
4061  *topfp = dd->perm[f->index];
4062  *topgp = dd->perm[g->index];
4063  *tophp = dd->perm[Cudd_Regular(h)->index];
4064 
4065  return(comple);
4066 
4067 } /* end of bddVarToCanonicalSimple */
4068 
4135 /*---------------------------------------------------------------------------*/
4136 /* Constant declarations */
4137 /*---------------------------------------------------------------------------*/
4138 
4139 #ifdef DD_CACHE_PROFILE
4140 #define DD_HYSTO_BINS 8
4141 #endif
4142 
4143 /*---------------------------------------------------------------------------*/
4144 /* Stucture declarations */
4145 /*---------------------------------------------------------------------------*/
4146 
4147 
4148 /*---------------------------------------------------------------------------*/
4149 /* Type declarations */
4150 /*---------------------------------------------------------------------------*/
4151 
4152 
4153 /*---------------------------------------------------------------------------*/
4154 /* Variable declarations */
4155 /*---------------------------------------------------------------------------*/
4156 
4157 //#ifndef lint
4158 //static char rcsid[] DD_UNUSED = "$Id: cuddCache.c,v 1.36 2012/02/05 01:07:18 fabio Exp $";
4159 //#endif
4160 
4161 /*---------------------------------------------------------------------------*/
4162 /* Macro declarations */
4163 /*---------------------------------------------------------------------------*/
4164 
4165 
4168 /*---------------------------------------------------------------------------*/
4169 /* Static function prototypes */
4170 /*---------------------------------------------------------------------------*/
4171 
4172 
4176 /*---------------------------------------------------------------------------*/
4177 /* Definition of exported functions */
4178 /*---------------------------------------------------------------------------*/
4179 
4180 /*---------------------------------------------------------------------------*/
4181 /* Definition of internal functions */
4182 /*---------------------------------------------------------------------------*/
4183 
4184 
4197 int
4199  DdManager * unique /* unique table */,
4200  unsigned int cacheSize /* initial size of the cache */,
4201  unsigned int maxCacheSize /* cache size beyond which no resizing occurs */)
4202 {
4203  int i;
4204  unsigned int logSize;
4205 #ifndef DD_CACHE_PROFILE
4206  DdNodePtr *mem;
4207  ptruint offset;
4208 #endif
4209 
4210  /* Round cacheSize to largest power of 2 not greater than the requested
4211  ** initial cache size. */
4212  logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2));
4213  cacheSize = 1 << logSize;
4214  unique->acache = ALLOC(DdCache,cacheSize+1);
4215  if (unique->acache == NULL) {
4216  unique->errorCode = CUDD_MEMORY_OUT;
4217  return(0);
4218  }
4219  /* If the size of the cache entry is a power of 2, we want to
4220  ** enforce alignment to that power of two. This happens when
4221  ** DD_CACHE_PROFILE is not defined. */
4222 #ifdef DD_CACHE_PROFILE
4223  unique->cache = unique->acache;
4224  unique->memused += (cacheSize) * sizeof(DdCache);
4225 #else
4226  mem = (DdNodePtr *) unique->acache;
4227  offset = (ptruint) mem & (sizeof(DdCache) - 1);
4228  mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr);
4229  unique->cache = (DdCache *) mem;
4230  assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0);
4231  unique->memused += (cacheSize+1) * sizeof(DdCache);
4232 #endif
4233  unique->cacheSlots = cacheSize;
4234  unique->cacheShift = sizeof(int) * 8 - logSize;
4235  unique->maxCacheHard = maxCacheSize;
4236  /* If cacheSlack is non-negative, we can resize. */
4237  unique->cacheSlack = (int) ddMin(maxCacheSize,
4239  2 * (int) cacheSize;
4240  Cudd_SetMinHit(unique,DD_MIN_HIT);
4241  /* Initialize to avoid division by 0 and immediate resizing. */
4242  unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1);
4243  unique->cacheHits = 0;
4244  unique->totCachehits = 0;
4245  /* The sum of cacheMisses and totCacheMisses is always correct,
4246  ** even though cacheMisses is larger than it should for the reasons
4247  ** explained above. */
4248  unique->totCacheMisses = -unique->cacheMisses;
4249  unique->cachecollisions = 0;
4250  unique->cacheinserts = 0;
4251  unique->cacheLastInserts = 0;
4252  unique->cachedeletions = 0;
4253 
4254  /* Initialize the cache */
4255  for (i = 0; (unsigned) i < cacheSize; i++) {
4256  unique->cache[i].h = 0; /* unused slots */
4257  unique->cache[i].data = NULL; /* invalid entry */
4258 #ifdef DD_CACHE_PROFILE
4259  unique->cache[i].count = 0;
4260 #endif
4261  }
4262 
4263  return(1);
4264 
4265 } /* end of cuddInitCache */
4266 
4267 
4282 void
4284  DdManager * table,
4285  ptruint op,
4286  DdNode * f,
4287  DdNode * g,
4288  DdNode * h,
4289  DdNode * data)
4290 {
4291  int posn;
4292  register DdCache *entry;
4293  ptruint uf, ug, uh;
4294 
4295  uf = (ptruint) f | (op & 0xe);
4296  ug = (ptruint) g | (op >> 4);
4297  uh = (ptruint) h;
4298 
4299  posn = ddCHash2(uh,uf,ug,table->cacheShift);
4300  entry = &table->cache[posn];
4301 
4302  table->cachecollisions += entry->data != NULL;
4303  table->cacheinserts++;
4304 
4305  entry->f = (DdNode *) uf;
4306  entry->g = (DdNode *) ug;
4307  entry->h = uh;
4308  entry->data = data;
4309 #ifdef DD_CACHE_PROFILE
4310  entry->count++;
4311 #endif
4312 
4313 } /* end of cuddCacheInsert */
4314 
4315 
4328 void
4330  DdManager * table,
4331  DD_CTFP op,
4332  DdNode * f,
4333  DdNode * g,
4334  DdNode * data)
4335 {
4336  int posn;
4337  register DdCache *entry;
4338 
4339  posn = ddCHash2(op,f,g,table->cacheShift);
4340  entry = &table->cache[posn];
4341 
4342  if (entry->data != NULL) {
4343  table->cachecollisions++;
4344  }
4345  table->cacheinserts++;
4346 
4347  entry->f = f;
4348  entry->g = g;
4349  entry->h = (ptruint) op;
4350  entry->data = data;
4351 #ifdef DD_CACHE_PROFILE
4352  entry->count++;
4353 #endif
4354 
4355 } /* end of cuddCacheInsert2 */
4356 
4357 
4370 void
4372  DdManager * table,
4373  DD_CTFP1 op,
4374  DdNode * f,
4375  DdNode * data)
4376 {
4377  int posn;
4378  register DdCache *entry;
4379 
4380  posn = ddCHash2(op,f,f,table->cacheShift);
4381  entry = &table->cache[posn];
4382 
4383  if (entry->data != NULL) {
4384  table->cachecollisions++;
4385  }
4386  table->cacheinserts++;
4387 
4388  entry->f = f;
4389  entry->g = f;
4390  entry->h = (ptruint) op;
4391  entry->data = data;
4392 #ifdef DD_CACHE_PROFILE
4393  entry->count++;
4394 #endif
4395 
4396 } /* end of cuddCacheInsert1 */
4397 
4398 
4412 DdNode *
4414  DdManager * table,
4415  ptruint op,
4416  DdNode * f,
4417  DdNode * g,
4418  DdNode * h)
4419 {
4420  int posn;
4421  DdCache *en,*cache;
4422  DdNode *data;
4423  ptruint uf, ug, uh;
4424 
4425  uf = (ptruint) f | (op & 0xe);
4426  ug = (ptruint) g | (op >> 4);
4427  uh = (ptruint) h;
4428 
4429  cache = table->cache;
4430 #ifdef DD_DEBUG
4431  if (cache == NULL) {
4432  return(NULL);
4433  }
4434 #endif
4435 
4436  posn = ddCHash2(uh,uf,ug,table->cacheShift);
4437  en = &cache[posn];
4438  if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug &&
4439  en->h==uh) {
4440  data = Cudd_Regular(en->data);
4441  table->cacheHits++;
4442  if (data->ref == 0) {
4443  cuddReclaim(table,data);
4444  }
4445  return(en->data);
4446  }
4447 
4448  /* Cache miss: decide whether to resize. */
4449  table->cacheMisses++;
4450 
4451  if (table->cacheSlack >= 0 &&
4452  table->cacheHits > table->cacheMisses * table->minHit) {
4453  cuddCacheResize(table);
4454  }
4455 
4456  return(NULL);
4457 
4458 } /* end of cuddCacheLookup */
4459 
4460 
4474 DdNode *
4476  DdManager * table,
4477  ptruint op,
4478  DdNode * f,
4479  DdNode * g,
4480  DdNode * h)
4481 {
4482  int posn;
4483  DdCache *en,*cache;
4484  DdNode *data;
4485  ptruint uf, ug, uh;
4486 
4487  uf = (ptruint) f | (op & 0xe);
4488  ug = (ptruint) g | (op >> 4);
4489  uh = (ptruint) h;
4490 
4491  cache = table->cache;
4492 #ifdef DD_DEBUG
4493  if (cache == NULL) {
4494  return(NULL);
4495  }
4496 #endif
4497 
4498  posn = ddCHash2(uh,uf,ug,table->cacheShift);
4499  en = &cache[posn];
4500  if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug &&
4501  en->h==uh) {
4502  data = Cudd_Regular(en->data);
4503  table->cacheHits++;
4504  if (data->ref == 0) {
4505  cuddReclaimZdd(table,data);
4506  }
4507  return(en->data);
4508  }
4509 
4510  /* Cache miss: decide whether to resize. */
4511  table->cacheMisses++;
4512 
4513  if (table->cacheSlack >= 0 &&
4514  table->cacheHits > table->cacheMisses * table->minHit) {
4515  cuddCacheResize(table);
4516  }
4517 
4518  return(NULL);
4519 
4520 } /* end of cuddCacheLookupZdd */
4521 
4522 
4536 DdNode *
4538  DdManager * table,
4539  DD_CTFP op,
4540  DdNode * f,
4541  DdNode * g)
4542 {
4543  int posn;
4544  DdCache *en,*cache;
4545  DdNode *data;
4546 
4547  cache = table->cache;
4548 #ifdef DD_DEBUG
4549  if (cache == NULL) {
4550  return(NULL);
4551  }
4552 #endif
4553 
4554  posn = ddCHash2(op,f,g,table->cacheShift);
4555  en = &cache[posn];
4556  if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) {
4557  data = Cudd_Regular(en->data);
4558  table->cacheHits++;
4559  if (data->ref == 0) {
4560  cuddReclaim(table,data);
4561  }
4562  return(en->data);
4563  }
4564 
4565  /* Cache miss: decide whether to resize. */
4566  table->cacheMisses++;
4567 
4568  if (table->cacheSlack >= 0 &&
4569  table->cacheHits > table->cacheMisses * table->minHit) {
4570  cuddCacheResize(table);
4571  }
4572 
4573  return(NULL);
4574 
4575 } /* end of cuddCacheLookup2 */
4576 
4577 
4590 DdNode *
4592  DdManager * table,
4593  DD_CTFP1 op,
4594  DdNode * f)
4595 {
4596  int posn;
4597  DdCache *en,*cache;
4598  DdNode *data;
4599 
4600  cache = table->cache;
4601 #ifdef DD_DEBUG
4602  if (cache == NULL) {
4603  return(NULL);
4604  }
4605 #endif
4606 
4607  posn = ddCHash2(op,f,f,table->cacheShift);
4608  en = &cache[posn];
4609  if (en->data != NULL && en->f==f && en->h==(ptruint)op) {
4610  data = Cudd_Regular(en->data);
4611  table->cacheHits++;
4612  if (data->ref == 0) {
4613  cuddReclaim(table,data);
4614  }
4615  return(en->data);
4616  }
4617 
4618  /* Cache miss: decide whether to resize. */
4619  table->cacheMisses++;
4620 
4621  if (table->cacheSlack >= 0 &&
4622  table->cacheHits > table->cacheMisses * table->minHit) {
4623  cuddCacheResize(table);
4624  }
4625 
4626  return(NULL);
4627 
4628 } /* end of cuddCacheLookup1 */
4629 
4630 
4644 DdNode *
4646  DdManager * table,
4647  DD_CTFP op,
4648  DdNode * f,
4649  DdNode * g)
4650 {
4651  int posn;
4652  DdCache *en,*cache;
4653  DdNode *data;
4654 
4655  cache = table->cache;
4656 #ifdef DD_DEBUG
4657  if (cache == NULL) {
4658  return(NULL);
4659  }
4660 #endif
4661 
4662  posn = ddCHash2(op,f,g,table->cacheShift);
4663  en = &cache[posn];
4664  if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) {
4665  data = Cudd_Regular(en->data);
4666  table->cacheHits++;
4667  if (data->ref == 0) {
4668  cuddReclaimZdd(table,data);
4669  }
4670  return(en->data);
4671  }
4672 
4673  /* Cache miss: decide whether to resize. */
4674  table->cacheMisses++;
4675 
4676  if (table->cacheSlack >= 0 &&
4677  table->cacheHits > table->cacheMisses * table->minHit) {
4678  cuddCacheResize(table);
4679  }
4680 
4681  return(NULL);
4682 
4683 } /* end of cuddCacheLookup2Zdd */
4684 
4685 
4698 DdNode *
4700  DdManager * table,
4701  DD_CTFP1 op,
4702  DdNode * f)
4703 {
4704  int posn;
4705  DdCache *en,*cache;
4706  DdNode *data;
4707 
4708  cache = table->cache;
4709 #ifdef DD_DEBUG
4710  if (cache == NULL) {
4711  return(NULL);
4712  }
4713 #endif
4714 
4715  posn = ddCHash2(op,f,f,table->cacheShift);
4716  en = &cache[posn];
4717  if (en->data != NULL && en->f==f && en->h==(ptruint)op) {
4718  data = Cudd_Regular(en->data);
4719  table->cacheHits++;
4720  if (data->ref == 0) {
4721  cuddReclaimZdd(table,data);
4722  }
4723  return(en->data);
4724  }
4725 
4726  /* Cache miss: decide whether to resize. */
4727  table->cacheMisses++;
4728 
4729  if (table->cacheSlack >= 0 &&
4730  table->cacheHits > table->cacheMisses * table->minHit) {
4731  cuddCacheResize(table);
4732  }
4733 
4734  return(NULL);
4735 
4736 } /* end of cuddCacheLookup1Zdd */
4737 
4738 
4755 DdNode *
4757  DdManager * table,
4758  ptruint op,
4759  DdNode * f,
4760  DdNode * g,
4761  DdNode * h)
4762 {
4763  int posn;
4764  DdCache *en,*cache;
4765  ptruint uf, ug, uh;
4766 
4767  uf = (ptruint) f | (op & 0xe);
4768  ug = (ptruint) g | (op >> 4);
4769  uh = (ptruint) h;
4770 
4771  cache = table->cache;
4772 #ifdef DD_DEBUG
4773  if (cache == NULL) {
4774  return(NULL);
4775  }
4776 #endif
4777  posn = ddCHash2(uh,uf,ug,table->cacheShift);
4778  en = &cache[posn];
4779 
4780  /* We do not reclaim here because the result should not be
4781  * referenced, but only tested for being a constant.
4782  */
4783  if (en->data != NULL &&
4784  en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) {
4785  table->cacheHits++;
4786  return(en->data);
4787  }
4788 
4789  /* Cache miss: decide whether to resize. */
4790  table->cacheMisses++;
4791 
4792  if (table->cacheSlack >= 0 &&
4793  table->cacheHits > table->cacheMisses * table->minHit) {
4794  cuddCacheResize(table);
4795  }
4796 
4797  return(NULL);
4798 
4799 } /* end of cuddConstantLookup */
4800 
4801 
4814 int
4816  DdManager * table,
4817  FILE * fp)
4818 {
4819  DdCache *cache = table->cache;
4820  int slots = table->cacheSlots;
4821  int nzeroes = 0;
4822  int i, retval;
4823  double exUsed;
4824 
4825 #ifdef DD_CACHE_PROFILE
4826  double count, mean, meansq, stddev, expected;
4827  long max, min;
4828  int imax, imin;
4829  double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */
4830  int nbins = DD_HYSTO_BINS;
4831  int bin;
4832  long thiscount;
4833  double totalcount, exStddev;
4834 
4835  meansq = mean = expected = 0.0;
4836  max = min = (long) cache[0].count;
4837  imax = imin = 0;
4838  totalcount = 0.0;
4839 
4840  hystogramQ = ALLOC(double, nbins);
4841  if (hystogramQ == NULL) {
4842  table->errorCode = CUDD_MEMORY_OUT;
4843  return(0);
4844  }
4845  hystogramR = ALLOC(double, nbins);
4846  if (hystogramR == NULL) {
4847  FREE(hystogramQ);
4848  table->errorCode = CUDD_MEMORY_OUT;
4849  return(0);
4850  }
4851  for (i = 0; i < nbins; i++) {
4852  hystogramQ[i] = 0;
4853  hystogramR[i] = 0;
4854  }
4855 
4856  for (i = 0; i < slots; i++) {
4857  thiscount = (long) cache[i].count;
4858  if (thiscount > max) {
4859  max = thiscount;
4860  imax = i;
4861  }
4862  if (thiscount < min) {
4863  min = thiscount;
4864  imin = i;
4865  }
4866  if (thiscount == 0) {
4867  nzeroes++;
4868  }
4869  count = (double) thiscount;
4870  mean += count;
4871  meansq += count * count;
4872  totalcount += count;
4873  expected += count * (double) i;
4874  bin = (i * nbins) / slots;
4875  hystogramQ[bin] += (double) thiscount;
4876  bin = i % nbins;
4877  hystogramR[bin] += (double) thiscount;
4878  }
4879  mean /= (double) slots;
4880  meansq /= (double) slots;
4881 
4882  /* Compute the standard deviation from both the data and the
4883  ** theoretical model for a random distribution. */
4884  stddev = sqrt(meansq - mean*mean);
4885  exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots);
4886 
4887  retval = fprintf(fp,"Cache average accesses = %g\n", mean);
4888  if (retval == EOF) return(0);
4889  retval = fprintf(fp,"Cache access standard deviation = %g ", stddev);
4890  if (retval == EOF) return(0);
4891  retval = fprintf(fp,"(expected = %g)\n", exStddev);
4892  if (retval == EOF) return(0);
4893  retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
4894  if (retval == EOF) return(0);
4895  retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
4896  if (retval == EOF) return(0);
4897  exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots));
4898  retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
4899  100.0 - (double) nzeroes * 100.0 / (double) slots,
4900  exUsed);
4901  if (retval == EOF) return(0);
4902 
4903  if (totalcount > 0) {
4904  expected /= totalcount;
4905  retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
4906  if (retval == EOF) return(0);
4907  retval = fprintf(fp," (expected bin value = %g)\nBy quotient:",
4908  expected);
4909  if (retval == EOF) return(0);
4910  for (i = nbins - 1; i>=0; i--) {
4911  retval = fprintf(fp," %.0f", hystogramQ[i]);
4912  if (retval == EOF) return(0);
4913  }
4914  retval = fprintf(fp,"\nBy residue: ");
4915  if (retval == EOF) return(0);
4916  for (i = nbins - 1; i>=0; i--) {
4917  retval = fprintf(fp," %.0f", hystogramR[i]);
4918  if (retval == EOF) return(0);
4919  }
4920  retval = fprintf(fp,"\n");
4921  if (retval == EOF) return(0);
4922  }
4923 
4924  FREE(hystogramQ);
4925  FREE(hystogramR);
4926 #else
4927  for (i = 0; i < slots; i++) {
4928  nzeroes += cache[i].h == 0;
4929  }
4930  exUsed = 100.0 *
4931  (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) /
4932  (double) slots));
4933  retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
4934  100.0 - (double) nzeroes * 100.0 / (double) slots,
4935  exUsed);
4936  if (retval == EOF) return(0);
4937 #endif
4938  return(1);
4939 
4940 } /* end of cuddCacheProfile */
4941 
4942 
4954 void
4956  DdManager * table)
4957 {
4958  DdCache *cache, *oldcache, *oldacache, *entry, *old;
4959  int i;
4960  int posn, shift;
4961  unsigned int slots, oldslots;
4962  double offset;
4963  int moved = 0;
4964  extern DD_OOMFP MMoutOfMemory;
4965  DD_OOMFP saveHandler;
4966 #ifndef DD_CACHE_PROFILE
4967  ptruint misalignment;
4968  DdNodePtr *mem;
4969 #endif
4970 
4971  oldcache = table->cache;
4972  oldacache = table->acache;
4973  oldslots = table->cacheSlots;
4974  slots = table->cacheSlots = oldslots << 1;
4975 
4976 #ifdef DD_VERBOSE
4977  (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n",
4978  oldslots, slots);
4979  (void) fprintf(table->err,
4980  "\thits = %g\tmisses = %g\thit ratio = %5.3f\n",
4981  table->cacheHits, table->cacheMisses,
4982  table->cacheHits / (table->cacheHits + table->cacheMisses));
4983 #endif
4984 
4985  saveHandler = MMoutOfMemory;
4986  MMoutOfMemory = Cudd_OutOfMem;
4987  table->acache = cache = ALLOC(DdCache,slots+1);
4988  MMoutOfMemory = saveHandler;
4989  /* If we fail to allocate the new table we just give up. */
4990  if (cache == NULL) {
4991 #ifdef DD_VERBOSE
4992  (void) fprintf(table->err,"Resizing failed. Giving up.\n");
4993 #endif
4994  table->cacheSlots = oldslots;
4995  table->acache = oldacache;
4996  /* Do not try to resize again. */
4997  table->maxCacheHard = oldslots - 1;
4998  table->cacheSlack = - (int) (oldslots + 1);
4999  return;
5000  }
5001  /* If the size of the cache entry is a power of 2, we want to
5002  ** enforce alignment to that power of two. This happens when
5003  ** DD_CACHE_PROFILE is not defined. */
5004 #ifdef DD_CACHE_PROFILE
5005  table->cache = cache;
5006 #else
5007  mem = (DdNodePtr *) cache;
5008  misalignment = (ptruint) mem & (sizeof(DdCache) - 1);
5009  mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr);
5010  table->cache = cache = (DdCache *) mem;
5011  assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0);
5012 #endif
5013  shift = --(table->cacheShift);
5014  table->memused += (slots - oldslots) * sizeof(DdCache);
5015  table->cacheSlack -= slots; /* need these many slots to double again */
5016 
5017  /* Clear new cache. */
5018  for (i = 0; (unsigned) i < slots; i++) {
5019  cache[i].data = NULL;
5020  cache[i].h = 0;
5021 #ifdef DD_CACHE_PROFILE
5022  cache[i].count = 0;
5023 #endif
5024  }
5025 
5026  /* Copy from old cache to new one. */
5027  for (i = 0; (unsigned) i < oldslots; i++) {
5028  old = &oldcache[i];
5029  if (old->data != NULL) {
5030  posn = ddCHash2(old->h,old->f,old->g,shift);
5031  entry = &cache[posn];
5032  entry->f = old->f;
5033  entry->g = old->g;
5034  entry->h = old->h;
5035  entry->data = old->data;
5036 #ifdef DD_CACHE_PROFILE
5037  entry->count = 1;
5038 #endif
5039  moved++;
5040  }
5041  }
5042 
5043  FREE(oldacache);
5044 
5045  /* Reinitialize measurements so as to avoid division by 0 and
5046  ** immediate resizing.
5047  */
5048  offset = (double) (int) (slots * table->minHit + 1);
5049  table->totCacheMisses += table->cacheMisses - offset;
5050  table->cacheMisses = offset;
5051  table->totCachehits += table->cacheHits;
5052  table->cacheHits = 0;
5053  table->cacheLastInserts = table->cacheinserts - (double) moved;
5054 
5055 } /* end of cuddCacheResize */
5056 
5057 
5069 void
5071  DdManager * table)
5072 {
5073  int i, slots;
5074  DdCache *cache;
5075 
5076  slots = table->cacheSlots;
5077  cache = table->cache;
5078  for (i = 0; i < slots; i++) {
5079  table->cachedeletions += cache[i].data != NULL;
5080  cache[i].data = NULL;
5081  }
5082  table->cacheLastInserts = table->cacheinserts;
5083 
5084  return;
5085 
5086 } /* end of cuddCacheFlush */
5087 
5088 
5101 int
5103  unsigned int value)
5104 {
5105  int floorLog = 0;
5106 #ifdef DD_DEBUG
5107  assert(value > 0);
5108 #endif
5109  while (value > 1) {
5110  floorLog++;
5111  value >>= 1;
5112  }
5113  return(floorLog);
5114 
5115 } /* end of cuddComputeFloorLog2 */
5116 
5117 /*---------------------------------------------------------------------------*/
5118 /* Definition of static functions */
5119 /*---------------------------------------------------------------------------*/
5184 /*---------------------------------------------------------------------------*/
5185 /* Constant declarations */
5186 /*---------------------------------------------------------------------------*/
5187 
5188 
5189 /*---------------------------------------------------------------------------*/
5190 /* Stucture declarations */
5191 /*---------------------------------------------------------------------------*/
5192 
5193 
5194 /*---------------------------------------------------------------------------*/
5195 /* Type declarations */
5196 /*---------------------------------------------------------------------------*/
5197 
5198 
5199 /*---------------------------------------------------------------------------*/
5200 /* Variable declarations */
5201 /*---------------------------------------------------------------------------*/
5202 
5203 //#ifndef lint
5204 //static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.37 2012/02/05 01:07:18 fabio Exp $";
5205 //#endif
5206 
5207 /*---------------------------------------------------------------------------*/
5208 /* Macro declarations */
5209 /*---------------------------------------------------------------------------*/
5210 
5211 
5214 /*---------------------------------------------------------------------------*/
5215 /* Static function prototypes */
5216 /*---------------------------------------------------------------------------*/
5217 
5218 static void debugFindParent (DdManager *table, DdNode *node);
5219 #if 0
5220 static void debugCheckParent (DdManager *table, DdNode *node);
5221 #endif
5222 
5226 /*---------------------------------------------------------------------------*/
5227 /* Definition of exported functions */
5228 /*---------------------------------------------------------------------------*/
5229 
5230 
5254 int
5256  DdManager * table)
5257 {
5258  unsigned int i;
5259  int j,count;
5260  int slots;
5261  DdNodePtr *nodelist;
5262  DdNode *f;
5263  DdNode *sentinel = &(table->sentinel);
5264  st_table *edgeTable; /* stores internal ref count for each node */
5265  st_generator *gen;
5266  int flag = 0;
5267  int totalNode;
5268  int deadNode;
5269  int index;
5270  int shift;
5271 
5272  edgeTable = st_init_table(st_ptrcmp,st_ptrhash);
5273  if (edgeTable == NULL) return(CUDD_OUT_OF_MEM);
5274 
5275  /* Check the BDD/ADD subtables. */
5276  for (i = 0; i < (unsigned) table->size; i++) {
5277  index = table->invperm[i];
5278  if (i != (unsigned) table->perm[index]) {
5279  (void) fprintf(table->err,
5280  "Permutation corrupted: invperm[%u] = %d\t perm[%d] = %d\n",
5281  i, index, index, table->perm[index]);
5282  }
5283  nodelist = table->subtables[i].nodelist;
5284  slots = table->subtables[i].slots;
5285  shift = table->subtables[i].shift;
5286 
5287  totalNode = 0;
5288  deadNode = 0;
5289  for (j = 0; j < slots; j++) { /* for each subtable slot */
5290  f = nodelist[j];
5291  while (f != sentinel) {
5292  totalNode++;
5293  if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
5294  if ((int) f->index != index) {
5295  (void) fprintf(table->err,
5296  "Error: node has illegal index\n");
5297  cuddPrintNode(f,table->err);
5298  flag = 1;
5299  }
5300  if ((unsigned) cuddI(table,cuddT(f)->index) <= i ||
5301  (unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index)
5302  <= i) {
5303  (void) fprintf(table->err,
5304  "Error: node has illegal children\n");
5305  cuddPrintNode(f,table->err);
5306  flag = 1;
5307  }
5308  if (Cudd_Regular(cuddT(f)) != cuddT(f)) {
5309  (void) fprintf(table->err,
5310  "Error: node has illegal form\n");
5311  cuddPrintNode(f,table->err);
5312  flag = 1;
5313  }
5314  if (cuddT(f) == cuddE(f)) {
5315  (void) fprintf(table->err,
5316  "Error: node has identical children\n");
5317  cuddPrintNode(f,table->err);
5318  flag = 1;
5319  }
5320  if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) {
5321  (void) fprintf(table->err,
5322  "Error: live node has dead children\n");
5323  cuddPrintNode(f,table->err);
5324  flag =1;
5325  }
5326  if (ddHash(cuddT(f),cuddE(f),shift) != j) {
5327  (void) fprintf(table->err, "Error: misplaced node\n");
5328  cuddPrintNode(f,table->err);
5329  flag =1;
5330  }
5331  /* Increment the internal reference count for the
5332  ** then child of the current node.
5333  */
5334  if (st_lookup_int(edgeTable,(char *)cuddT(f),&count)) {
5335  count++;
5336  } else {
5337  count = 1;
5338  }
5339  if (st_insert(edgeTable,(char *)cuddT(f),
5340  (char *)(long)count) == ST_OUT_OF_MEM) {
5341  st_free_table(edgeTable);
5342  return(CUDD_OUT_OF_MEM);
5343  }
5344 
5345  /* Increment the internal reference count for the
5346  ** else child of the current node.
5347  */
5348  if (st_lookup_int(edgeTable,(char *)Cudd_Regular(cuddE(f)),
5349  &count)) {
5350  count++;
5351  } else {
5352  count = 1;
5353  }
5354  if (st_insert(edgeTable,(char *)Cudd_Regular(cuddE(f)),
5355  (char *)(long)count) == ST_OUT_OF_MEM) {
5356  st_free_table(edgeTable);
5357  return(CUDD_OUT_OF_MEM);
5358  }
5359  } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
5360  deadNode++;
5361 #if 0
5362  debugCheckParent(table,f);
5363 #endif
5364  } else {
5365  fprintf(table->err,
5366  "Error: node has illegal Then or Else pointers\n");
5367  cuddPrintNode(f,table->err);
5368  flag = 1;
5369  }
5370 
5371  f = f->next;
5372  } /* for each element of the collision list */
5373  } /* for each subtable slot */
5374 
5375  if ((unsigned) totalNode != table->subtables[i].keys) {
5376  fprintf(table->err,"Error: wrong number of total nodes\n");
5377  flag = 1;
5378  }
5379  if ((unsigned) deadNode != table->subtables[i].dead) {
5380  fprintf(table->err,"Error: wrong number of dead nodes\n");
5381  flag = 1;
5382  }
5383  } /* for each BDD/ADD subtable */
5384 
5385  /* Check the ZDD subtables. */
5386  for (i = 0; i < (unsigned) table->sizeZ; i++) {
5387  index = table->invpermZ[i];
5388  if (i != (unsigned) table->permZ[index]) {
5389  (void) fprintf(table->err,
5390  "Permutation corrupted: invpermZ[%u] = %d\t permZ[%d] = %d in ZDD\n",
5391  i, index, index, table->permZ[index]);
5392  }
5393  nodelist = table->subtableZ[i].nodelist;
5394  slots = table->subtableZ[i].slots;
5395 
5396  totalNode = 0;
5397  deadNode = 0;
5398  for (j = 0; j < slots; j++) { /* for each subtable slot */
5399  f = nodelist[j];
5400  while (f != NULL) {
5401  totalNode++;
5402  if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
5403  if ((int) f->index != index) {
5404  (void) fprintf(table->err,
5405  "Error: ZDD node has illegal index\n");
5406  cuddPrintNode(f,table->err);
5407  flag = 1;
5408  }
5409  if (Cudd_IsComplement(cuddT(f)) ||
5410  Cudd_IsComplement(cuddE(f))) {
5411  (void) fprintf(table->err,
5412  "Error: ZDD node has complemented children\n");
5413  cuddPrintNode(f,table->err);
5414  flag = 1;
5415  }
5416  if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i ||
5417  (unsigned) cuddIZ(table,cuddE(f)->index) <= i) {
5418  (void) fprintf(table->err,
5419  "Error: ZDD node has illegal children\n");
5420  cuddPrintNode(f,table->err);
5421  cuddPrintNode(cuddT(f),table->err);
5422  cuddPrintNode(cuddE(f),table->err);
5423  flag = 1;
5424  }
5425  if (cuddT(f) == DD_ZERO(table)) {
5426  (void) fprintf(table->err,
5427  "Error: ZDD node has zero then child\n");
5428  cuddPrintNode(f,table->err);
5429  flag = 1;
5430  }
5431  if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) {
5432  (void) fprintf(table->err,
5433  "Error: ZDD live node has dead children\n");
5434  cuddPrintNode(f,table->err);
5435  flag =1;
5436  }
5437  /* Increment the internal reference count for the
5438  ** then child of the current node.
5439  */
5440  if (st_lookup_int(edgeTable,(char *)cuddT(f),&count)) {
5441  count++;
5442  } else {
5443  count = 1;
5444  }
5445  if (st_insert(edgeTable,(char *)cuddT(f),
5446  (char *)(long)count) == ST_OUT_OF_MEM) {
5447  st_free_table(edgeTable);
5448  return(CUDD_OUT_OF_MEM);
5449  }
5450 
5451  /* Increment the internal reference count for the
5452  ** else child of the current node.
5453  */
5454  if (st_lookup_int(edgeTable,(char *)cuddE(f),&count)) {
5455  count++;
5456  } else {
5457  count = 1;
5458  }
5459  if (st_insert(edgeTable,(char *)cuddE(f),
5460  (char *)(long)count) == ST_OUT_OF_MEM) {
5461  st_free_table(edgeTable);
5462  table->errorCode = CUDD_MEMORY_OUT;
5463  return(CUDD_OUT_OF_MEM);
5464  }
5465  } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
5466  deadNode++;
5467 #if 0
5468  debugCheckParent(table,f);
5469 #endif
5470  } else {
5471  fprintf(table->err,
5472  "Error: ZDD node has illegal Then or Else pointers\n");
5473  cuddPrintNode(f,table->err);
5474  flag = 1;
5475  }
5476 
5477  f = f->next;
5478  } /* for each element of the collision list */
5479  } /* for each subtable slot */
5480 
5481  if ((unsigned) totalNode != table->subtableZ[i].keys) {
5482  fprintf(table->err,
5483  "Error: wrong number of total nodes in ZDD\n");
5484  flag = 1;
5485  }
5486  if ((unsigned) deadNode != table->subtableZ[i].dead) {
5487  fprintf(table->err,
5488  "Error: wrong number of dead nodes in ZDD\n");
5489  flag = 1;
5490  }
5491  } /* for each ZDD subtable */
5492 
5493  /* Check the constant table. */
5494  nodelist = table->constants.nodelist;
5495  slots = table->constants.slots;
5496 
5497  totalNode = 0;
5498  deadNode = 0;
5499  for (j = 0; j < slots; j++) {
5500  f = nodelist[j];
5501  while (f != NULL) {
5502  totalNode++;
5503  if (f->ref != 0) {
5504  if (f->index != CUDD_CONST_INDEX) {
5505  fprintf(table->err,"Error: node has illegal index\n");
5506 #if SIZEOF_VOID_P == 8
5507  fprintf(table->err,
5508  " node 0x%lx, id = %u, ref = %u, value = %g\n",
5509  (ptruint)f,f->index,f->ref,cuddV(f));
5510 #else
5511  fprintf(table->err,
5512  " node 0x%x, id = %hu, ref = %hu, value = %g\n",
5513  (ptruint)f,f->index,f->ref,cuddV(f));
5514 #endif
5515  flag = 1;
5516  }
5517  } else {
5518  deadNode++;
5519  }
5520  f = f->next;
5521  }
5522  }
5523  if ((unsigned) totalNode != table->constants.keys) {
5524  (void) fprintf(table->err,
5525  "Error: wrong number of total nodes in constants\n");
5526  flag = 1;
5527  }
5528  if ((unsigned) deadNode != table->constants.dead) {
5529  (void) fprintf(table->err,
5530  "Error: wrong number of dead nodes in constants\n");
5531  flag = 1;
5532  }
5533  gen = st_init_gen(edgeTable);
5534  while (st_gen(gen, &f, &count)) {
5535  if (count > (int)(f->ref) && f->ref != DD_MAXREF) {
5536 #if SIZEOF_VOID_P == 8
5537  fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
5538 #else
5539  fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
5540 #endif
5541  debugFindParent(table,f);
5542  flag = 1;
5543  }
5544  }
5545  st_free_gen(gen);
5546  st_free_table(edgeTable);
5547 
5548  return (flag);
5549 
5550 } /* end of Cudd_DebugCheck */
5551 
5552 
5576 int
5578  DdManager * table)
5579 {
5580  int size;
5581  int i,j;
5582  DdNodePtr *nodelist;
5583  DdNode *node;
5584  DdNode *sentinel = &(table->sentinel);
5585  DdSubtable *subtable;
5586  int keys;
5587  int dead;
5588  int count = 0;
5589  int totalKeys = 0;
5590  int totalSlots = 0;
5591  int totalDead = 0;
5592  int nonEmpty = 0;
5593  unsigned int slots;
5594  int logSlots;
5595  int shift;
5596 
5597  size = table->size;
5598 
5599  for (i = 0; i < size; i++) {
5600  subtable = &(table->subtables[i]);
5601  nodelist = subtable->nodelist;
5602  keys = subtable->keys;
5603  dead = subtable->dead;
5604  totalKeys += keys;
5605  slots = subtable->slots;
5606  shift = subtable->shift;
5607  logSlots = sizeof(int) * 8 - shift;
5608  if (((slots >> logSlots) << logSlots) != slots) {
5609  (void) fprintf(table->err,
5610  "Unique table %d is not the right power of 2\n", i);
5611  (void) fprintf(table->err,
5612  " slots = %u shift = %d\n", slots, shift);
5613  }
5614  totalSlots += slots;
5615  totalDead += dead;
5616  for (j = 0; (unsigned) j < slots; j++) {
5617  node = nodelist[j];
5618  if (node != sentinel) {
5619  nonEmpty++;
5620  }
5621  while (node != sentinel) {
5622  keys--;
5623  if (node->ref == 0) {
5624  dead--;
5625  }
5626  node = node->next;
5627  }
5628  }
5629  if (keys != 0) {
5630  (void) fprintf(table->err, "Wrong number of keys found \
5631 in unique table %d (difference=%d)\n", i, keys);
5632  count++;
5633  }
5634  if (dead != 0) {
5635  (void) fprintf(table->err, "Wrong number of dead found \
5636 in unique table no. %d (difference=%d)\n", i, dead);
5637  }
5638  } /* for each BDD/ADD subtable */
5639 
5640  /* Check the ZDD subtables. */
5641  size = table->sizeZ;
5642 
5643  for (i = 0; i < size; i++) {
5644  subtable = &(table->subtableZ[i]);
5645  nodelist = subtable->nodelist;
5646  keys = subtable->keys;
5647  dead = subtable->dead;
5648  totalKeys += keys;
5649  totalSlots += subtable->slots;
5650  totalDead += dead;
5651  for (j = 0; (unsigned) j < subtable->slots; j++) {
5652  node = nodelist[j];
5653  if (node != NULL) {
5654  nonEmpty++;
5655  }
5656  while (node != NULL) {
5657  keys--;
5658  if (node->ref == 0) {
5659  dead--;
5660  }
5661  node = node->next;
5662  }
5663  }
5664  if (keys != 0) {
5665  (void) fprintf(table->err, "Wrong number of keys found \
5666 in ZDD unique table no. %d (difference=%d)\n", i, keys);
5667  count++;
5668  }
5669  if (dead != 0) {
5670  (void) fprintf(table->err, "Wrong number of dead found \
5671 in ZDD unique table no. %d (difference=%d)\n", i, dead);
5672  }
5673  } /* for each ZDD subtable */
5674 
5675  /* Check the constant table. */
5676  subtable = &(table->constants);
5677  nodelist = subtable->nodelist;
5678  keys = subtable->keys;
5679  dead = subtable->dead;
5680  totalKeys += keys;
5681  totalSlots += subtable->slots;
5682  totalDead += dead;
5683  for (j = 0; (unsigned) j < subtable->slots; j++) {
5684  node = nodelist[j];
5685  if (node != NULL) {
5686  nonEmpty++;
5687  }
5688  while (node != NULL) {
5689  keys--;
5690  if (node->ref == 0) {
5691  dead--;
5692  }
5693  node = node->next;
5694  }
5695  }
5696  if (keys != 0) {
5697  (void) fprintf(table->err, "Wrong number of keys found \
5698 in the constant table (difference=%d)\n", keys);
5699  count++;
5700  }
5701  if (dead != 0) {
5702  (void) fprintf(table->err, "Wrong number of dead found \
5703 in the constant table (difference=%d)\n", dead);
5704  }
5705  if ((unsigned) totalKeys != table->keys + table->keysZ) {
5706  (void) fprintf(table->err, "Wrong number of total keys found \
5707 (difference=%d)\n", (int) (totalKeys-table->keys));
5708  }
5709  if ((unsigned) totalSlots != table->slots) {
5710  (void) fprintf(table->err, "Wrong number of total slots found \
5711 (difference=%d)\n", (int) (totalSlots-table->slots));
5712  }
5713  if (table->minDead != (unsigned) (table->gcFrac * table->slots)) {
5714  (void) fprintf(table->err, "Wrong number of minimum dead found \
5715 (%u vs. %u)\n", table->minDead,
5716  (unsigned) (table->gcFrac * (double) table->slots));
5717  }
5718  if ((unsigned) totalDead != table->dead + table->deadZ) {
5719  (void) fprintf(table->err, "Wrong number of total dead found \
5720 (difference=%d)\n", (int) (totalDead-table->dead));
5721  }
5722  (void) fprintf(table->out,"Average length of non-empty lists = %g\n",
5723  (double) table->keys / (double) nonEmpty);
5724 
5725  return(count);
5726 
5727 } /* end of Cudd_CheckKeys */
5728 
5729 
5730 /*---------------------------------------------------------------------------*/
5731 /* Definition of internal functions */
5732 /*---------------------------------------------------------------------------*/
5733 
5734 
5757 int
5759  DdManager * dd)
5760 {
5761  int ntables = dd->size;
5762  DdSubtable *subtables = dd->subtables;
5763  int i, /* loop index */
5764  nodes, /* live nodes in i-th layer */
5765  retval, /* return value of fprintf */
5766  largest = -1, /* index of the table with most live nodes */
5767  maxnodes = -1, /* maximum number of live nodes in a table */
5768  nonempty = 0; /* number of tables with live nodes */
5769 
5770  /* Print header. */
5771 #if SIZEOF_VOID_P == 8
5772  retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n",
5773  (ptruint) dd);
5774 #else
5775  retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n",
5776  (ptruint) dd);
5777 #endif
5778  if (retval == EOF) return 0;
5779 
5780  /* Print number of live nodes for each nonempty table. */
5781  for (i=0; i<ntables; i++) {
5782  nodes = subtables[i].keys - subtables[i].dead;
5783  if (nodes) {
5784  nonempty++;
5785  retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes);
5786  if (retval == EOF) return 0;
5787  if (nodes > maxnodes) {
5788  maxnodes = nodes;
5789  largest = i;
5790  }
5791  }
5792  }
5793 
5794  nodes = dd->constants.keys - dd->constants.dead;
5795  if (nodes) {
5796  nonempty++;
5797  retval = fprintf(dd->out,"const: %5d nodes\n", nodes);
5798  if (retval == EOF) return 0;
5799  if (nodes > maxnodes) {
5800  maxnodes = nodes;
5801  largest = CUDD_CONST_INDEX;
5802  }
5803  }
5804 
5805  /* Print summary. */
5806  retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ",
5807  ntables+1, nonempty, largest);
5808  if (retval == EOF) return 0;
5809  retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes);
5810  if (retval == EOF) return 0;
5811 
5812  return(1);
5813 
5814 } /* end of cuddHeapProfile */
5815 
5816 
5828 void
5830  DdNode * f,
5831  FILE *fp)
5832 {
5833  f = Cudd_Regular(f);
5834 #if SIZEOF_VOID_P == 8
5835  (void) fprintf(fp," node 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
5836 #else
5837  (void) fprintf(fp," node 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
5838 #endif
5839 
5840 } /* end of cuddPrintNode */
5841 
5842 
5843 
5865 void
5867  DdManager * dd /* manager */,
5868  MtrNode * root /* root of the group tree */,
5869  int zdd /* 0: BDD; 1: ZDD */,
5870  int silent /* flag to check tree syntax only */)
5871 {
5872  MtrNode *node;
5873  int level;
5874 
5875  assert(root != NULL);
5876  assert(root->younger == NULL || root->younger->elder == root);
5877  assert(root->elder == NULL || root->elder->younger == root);
5878  if (zdd) {
5879  level = dd->permZ[root->index];
5880  } else {
5881  level = dd->perm[root->index];
5882  }
5883  if (!silent) (void) printf("(%d",level);
5884  if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
5885  if (!silent) (void) printf(",");
5886  } else {
5887  node = root->child;
5888  while (node != NULL) {
5889  assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
5890  assert(node->parent == root);
5891  cuddPrintVarGroups(dd,node,zdd,silent);
5892  node = node->younger;
5893  }
5894  }
5895  if (!silent) {
5896  (void) printf("%d", (int) (level + root->size - 1));
5897  if (root->flags != MTR_DEFAULT) {
5898  (void) printf("|");
5899  if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
5900  if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
5901  if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
5902  }
5903  (void) printf(")");
5904  if (root->parent == NULL) (void) printf("\n");
5905  }
5906  assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
5907  return;
5908 
5909 } /* end of cuddPrintVarGroups */
5910 
5911 
5912 /*---------------------------------------------------------------------------*/
5913 /* Definition of static functions */
5914 /*---------------------------------------------------------------------------*/
5915 
5916 
5928 static void
5930  DdManager * table,
5931  DdNode * node)
5932 {
5933  int i,j;
5934  int slots;
5935  DdNodePtr *nodelist;
5936  DdNode *f;
5937 
5938  for (i = 0; i < cuddI(table,node->index); i++) {
5939  nodelist = table->subtables[i].nodelist;
5940  slots = table->subtables[i].slots;
5941 
5942  for (j=0;j<slots;j++) {
5943  f = nodelist[j];
5944  while (f != NULL) {
5945  if (cuddT(f) == node || Cudd_Regular(cuddE(f)) == node) {
5946 #if SIZEOF_VOID_P == 8
5947  (void) fprintf(table->out,"parent is at 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",
5948  (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
5949 #else
5950  (void) fprintf(table->out,"parent is at 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",
5951  (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
5952 #endif
5953  }
5954  f = f->next;
5955  }
5956  }
5957  }
5958 
5959 } /* end of debugFindParent */
5960 
5961 
5962 #if 0
5963 
5975 static void
5976 debugCheckParent(
5977  DdManager * table,
5978  DdNode * node)
5979 {
5980  int i,j;
5981  int slots;
5982  DdNode **nodelist,*f;
5983 
5984  for (i = 0; i < cuddI(table,node->index); i++) {
5985  nodelist = table->subtables[i].nodelist;
5986  slots = table->subtables[i].slots;
5987 
5988  for (j=0;j<slots;j++) {
5989  f = nodelist[j];
5990  while (f != NULL) {
5991  if ((Cudd_Regular(cuddE(f)) == node || cuddT(f) == node) && f->ref != 0) {
5992  (void) fprintf(table->err,
5993  "error with zero ref count\n");
5994  (void) fprintf(table->err,"parent is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f));
5995  (void) fprintf(table->err,"child is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node));
5996  }
5997  f = f->next;
5998  }
5999  }
6000  }
6001 }
6002 #endif
6003 
6062 /*---------------------------------------------------------------------------*/
6063 /* Constant declarations */
6064 /*---------------------------------------------------------------------------*/
6065 
6066 
6067 /*---------------------------------------------------------------------------*/
6068 /* Stucture declarations */
6069 /*---------------------------------------------------------------------------*/
6070 
6071 
6072 /*---------------------------------------------------------------------------*/
6073 /* Type declarations */
6074 /*---------------------------------------------------------------------------*/
6075 
6076 
6077 /*---------------------------------------------------------------------------*/
6078 /* Variable declarations */
6079 /*---------------------------------------------------------------------------*/
6080 
6081 //#ifndef lint
6082 //static char rcsid[] DD_UNUSED = "$Id: cuddCof.c,v 1.11 2012/02/05 01:07:18 fabio Exp $";
6083 //#endif
6084 
6085 /*---------------------------------------------------------------------------*/
6086 /* Macro declarations */
6087 /*---------------------------------------------------------------------------*/
6088 
6089 
6092 /*---------------------------------------------------------------------------*/
6093 /* Static function prototypes */
6094 /*---------------------------------------------------------------------------*/
6095 
6096 
6100 /*---------------------------------------------------------------------------*/
6101 /* Definition of exported functions */
6102 /*---------------------------------------------------------------------------*/
6103 
6104 
6118 DdNode *
6120  DdManager * dd,
6121  DdNode * f,
6122  DdNode * g)
6123 {
6124  DdNode *res,*zero;
6125 
6126  zero = Cudd_Not(DD_ONE(dd));
6127  if (g == zero || g == DD_ZERO(dd)) {
6128  (void) fprintf(dd->err,"Cudd_Cofactor: Invalid restriction 1\n");
6130  return(NULL);
6131  }
6132  do {
6133  dd->reordered = 0;
6134  res = cuddCofactorRecur(dd,f,g);
6135  } while (dd->reordered == 1);
6136  return(res);
6137 
6138 } /* end of Cudd_Cofactor */
6139 
6140 
6154 int
6156  DdManager * dd,
6157  DdNode * g)
6158 {
6159  DdNode *g1,*g0,*one,*zero;
6160 
6161  one = DD_ONE(dd);
6162  if (g == one) return(1);
6163  if (Cudd_IsConstant(g)) return(0);
6164 
6165  zero = Cudd_Not(one);
6166  cuddGetBranches(g,&g1,&g0);
6167 
6168  if (g0 == zero) {
6169  return(Cudd_CheckCube(dd, g1));
6170  }
6171  if (g1 == zero) {
6172  return(Cudd_CheckCube(dd, g0));
6173  }
6174  return(0);
6175 
6176 } /* end of Cudd_CheckCube */
6177 
6178 
6179 /*---------------------------------------------------------------------------*/
6180 /* Definition of internal functions */
6181 /*---------------------------------------------------------------------------*/
6182 
6183 
6195 void
6197  DdNode * g,
6198  DdNode ** g1,
6199  DdNode ** g0)
6200 {
6201  DdNode *G = Cudd_Regular(g);
6202 
6203  *g1 = cuddT(G);
6204  *g0 = cuddE(G);
6205  if (Cudd_IsComplement(g)) {
6206  *g1 = Cudd_Not(*g1);
6207  *g0 = Cudd_Not(*g0);
6208  }
6209 
6210 } /* end of cuddGetBranches */
6211 
6212 
6225 DdNode *
6227  DdManager * dd,
6228  DdNode * f,
6229  DdNode * g)
6230 {
6231  DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r;
6232  unsigned int topf,topg;
6233  int comple;
6234 
6235  statLine(dd);
6236  F = Cudd_Regular(f);
6237  if (cuddIsConstant(F)) return(f);
6238 
6239  one = DD_ONE(dd);
6240 
6241  /* The invariant g != 0 is true on entry to this procedure and is
6242  ** recursively maintained by it. Therefore it suffices to test g
6243  ** against one to make sure it is not constant.
6244  */
6245  if (g == one) return(f);
6246  /* From now on, f and g are known not to be constants. */
6247 
6248  comple = f != F;
6249  r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g);
6250  if (r != NULL) {
6251  return(Cudd_NotCond(r,comple));
6252  }
6253 
6254  topf = dd->perm[F->index];
6255  G = Cudd_Regular(g);
6256  topg = dd->perm[G->index];
6257 
6258  /* We take the cofactors of F because we are going to rely on
6259  ** the fact that the cofactors of the complement are the complements
6260  ** of the cofactors to better utilize the cache. Variable comple
6261  ** remembers whether we have to complement the result or not.
6262  */
6263  if (topf <= topg) {
6264  f1 = cuddT(F); f0 = cuddE(F);
6265  } else {
6266  f1 = f0 = F;
6267  }
6268  if (topg <= topf) {
6269  g1 = cuddT(G); g0 = cuddE(G);
6270  if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); }
6271  } else {
6272  g1 = g0 = g;
6273  }
6274 
6275  zero = Cudd_Not(one);
6276  if (topf >= topg) {
6277  if (g0 == zero || g0 == DD_ZERO(dd)) {
6278  r = cuddCofactorRecur(dd, f1, g1);
6279  } else if (g1 == zero || g1 == DD_ZERO(dd)) {
6280  r = cuddCofactorRecur(dd, f0, g0);
6281  } else {
6282  (void) fprintf(dd->out,
6283  "Cudd_Cofactor: Invalid restriction 2\n");
6285  return(NULL);
6286  }
6287  if (r == NULL) return(NULL);
6288  } else /* if (topf < topg) */ {
6289  t = cuddCofactorRecur(dd, f1, g);
6290  if (t == NULL) return(NULL);
6291  cuddRef(t);
6292  e = cuddCofactorRecur(dd, f0, g);
6293  if (e == NULL) {
6294  Cudd_RecursiveDeref(dd, t);
6295  return(NULL);
6296  }
6297  cuddRef(e);
6298 
6299  if (t == e) {
6300  r = t;
6301  } else if (Cudd_IsComplement(t)) {
6302  r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e));
6303  if (r != NULL)
6304  r = Cudd_Not(r);
6305  } else {
6306  r = cuddUniqueInter(dd,(int)F->index,t,e);
6307  }
6308  if (r == NULL) {
6309  Cudd_RecursiveDeref(dd ,e);
6310  Cudd_RecursiveDeref(dd ,t);
6311  return(NULL);
6312  }
6313  cuddDeref(t);
6314  cuddDeref(e);
6315  }
6316 
6317  cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r);
6318 
6319  return(Cudd_NotCond(r,comple));
6320 
6321 } /* end of cuddCofactorRecur */
6322 
6323 
6324 /*---------------------------------------------------------------------------*/
6325 /* Definition of static functions */
6326 /*---------------------------------------------------------------------------*/
6327 
6398 /*---------------------------------------------------------------------------*/
6399 /* Constant declarations */
6400 /*---------------------------------------------------------------------------*/
6401 
6402 
6403 /*---------------------------------------------------------------------------*/
6404 /* Stucture declarations */
6405 /*---------------------------------------------------------------------------*/
6406 
6407 /*---------------------------------------------------------------------------*/
6408 /* Type declarations */
6409 /*---------------------------------------------------------------------------*/
6410 
6411 /*---------------------------------------------------------------------------*/
6412 /* Variable declarations */
6413 /*---------------------------------------------------------------------------*/
6414 
6415 //#ifndef lint
6416 //static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.30 2012/02/05 01:07:18 fabio Exp $";
6417 //#endif
6418 
6419 #ifdef DD_STATS
6420 static int ddTotalShuffles;
6421 #endif
6422 
6423 /*---------------------------------------------------------------------------*/
6424 /* Macro declarations */
6425 /*---------------------------------------------------------------------------*/
6426 
6429 /*---------------------------------------------------------------------------*/
6430 /* Static function prototypes */
6431 /*---------------------------------------------------------------------------*/
6432 
6433 static int getMaxBinomial (int n);
6434 static DdHalfWord ** getMatrix (int rows, int cols);
6435 static void freeMatrix (DdHalfWord **matrix);
6436 static int getLevelKeys (DdManager *table, int l);
6437 static int ddShuffle (DdManager *table, DdHalfWord *permutation, int lower, int upper);
6438 static int ddSiftUp (DdManager *table, int x, int xLow);
6439 static int updateUB (DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper);
6440 static int ddCountRoots (DdManager *table, int lower, int upper);
6441 static void ddClearGlobal (DdManager *table, int lower, int maxlevel);
6442 static int computeLB (DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level);
6443 static int updateEntry (DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper);
6444 static void pushDown (DdHalfWord *order, int j, int level);
6445 static DdHalfWord * initSymmInfo (DdManager *table, int lower, int upper);
6446 static int checkSymmInfo (DdManager *table, DdHalfWord *symmInfo, int index, int level);
6447 
6451 /*---------------------------------------------------------------------------*/
6452 /* Definition of exported functions */
6453 /*---------------------------------------------------------------------------*/
6454 
6455 /*---------------------------------------------------------------------------*/
6456 /* Definition of internal functions */
6457 /*---------------------------------------------------------------------------*/
6458 
6459 
6473 int
6475  DdManager * table,
6476  int lower,
6477  int upper)
6478 {
6479  int k, i, j;
6480  int maxBinomial, oldSubsets, newSubsets;
6481  int subsetCost;
6482  int size; /* number of variables to be reordered */
6483  int unused, nvars, level, result;
6484  int upperBound, lowerBound, cost;
6485  int roots;
6486  char *mask = NULL;
6487  DdHalfWord *symmInfo = NULL;
6488  DdHalfWord **newOrder = NULL;
6489  DdHalfWord **oldOrder = NULL;
6490  int *newCost = NULL;
6491  int *oldCost = NULL;
6492  DdHalfWord **tmpOrder;
6493  int *tmpCost;
6494  DdHalfWord *bestOrder = NULL;
6495  DdHalfWord *order;
6496 #ifdef DD_STATS
6497  int ddTotalSubsets;
6498 #endif
6499 
6500  /* Restrict the range to be reordered by excluding unused variables
6501  ** at the two ends. */
6502  while (table->subtables[lower].keys == 1 &&
6503  table->vars[table->invperm[lower]]->ref == 1 &&
6504  lower < upper)
6505  lower++;
6506  while (table->subtables[upper].keys == 1 &&
6507  table->vars[table->invperm[upper]]->ref == 1 &&
6508  lower < upper)
6509  upper--;
6510  if (lower == upper) return(1); /* trivial problem */
6511 
6512  /* Apply symmetric sifting to get a good upper bound and to extract
6513  ** symmetry information. */
6514  result = cuddSymmSiftingConv(table,lower,upper);
6515  if (result == 0) goto cuddExactOutOfMem;
6516 
6517 #ifdef DD_STATS
6518  (void) fprintf(table->out,"\n");
6519  ddTotalShuffles = 0;
6520  ddTotalSubsets = 0;
6521 #endif
6522 
6523  /* Initialization. */
6524  nvars = table->size;
6525  size = upper - lower + 1;
6526  /* Count unused variable among those to be reordered. This is only
6527  ** used to compute maxBinomial. */
6528  unused = 0;
6529  for (i = lower + 1; i < upper; i++) {
6530  if (table->subtables[i].keys == 1 &&
6531  table->vars[table->invperm[i]]->ref == 1)
6532  unused++;
6533  }
6534 
6535  /* Find the maximum number of subsets we may have to store. */
6536  maxBinomial = getMaxBinomial(size - unused);
6537  if (maxBinomial == -1) goto cuddExactOutOfMem;
6538 
6539  newOrder = getMatrix(maxBinomial, size);
6540  if (newOrder == NULL) goto cuddExactOutOfMem;
6541 
6542  newCost = ALLOC(int, maxBinomial);
6543  if (newCost == NULL) goto cuddExactOutOfMem;
6544 
6545  oldOrder = getMatrix(maxBinomial, size);
6546  if (oldOrder == NULL) goto cuddExactOutOfMem;
6547 
6548  oldCost = ALLOC(int, maxBinomial);
6549  if (oldCost == NULL) goto cuddExactOutOfMem;
6550 
6551  bestOrder = ALLOC(DdHalfWord, size);
6552  if (bestOrder == NULL) goto cuddExactOutOfMem;
6553 
6554  mask = ALLOC(char, nvars);
6555  if (mask == NULL) goto cuddExactOutOfMem;
6556 
6557  symmInfo = initSymmInfo(table, lower, upper);
6558  if (symmInfo == NULL) goto cuddExactOutOfMem;
6559 
6560  roots = ddCountRoots(table, lower, upper);
6561 
6562  /* Initialize the old order matrix for the empty subset and the best
6563  ** order to the current order. The cost for the empty subset includes
6564  ** the cost of the levels between upper and the constants. These levels
6565  ** are not going to change. Hence, we count them only once.
6566  */
6567  oldSubsets = 1;
6568  for (i = 0; i < size; i++) {
6569  oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower];
6570  }
6571  subsetCost = table->constants.keys;
6572  for (i = upper + 1; i < nvars; i++)
6573  subsetCost += getLevelKeys(table,i);
6574  oldCost[0] = subsetCost;
6575  /* The upper bound is initialized to the current size of the BDDs. */
6576  upperBound = table->keys - table->isolated;
6577 
6578  /* Now consider subsets of increasing size. */
6579  for (k = 1; k <= size; k++) {
6580 #ifdef DD_STATS
6581  (void) fprintf(table->out,"Processing subsets of size %d\n", k);
6582  fflush(table->out);
6583 #endif
6584  newSubsets = 0;
6585  level = size - k; /* offset of first bottom variable */
6586 
6587  for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */
6588  order = oldOrder[i];
6589  cost = oldCost[i];
6590  lowerBound = computeLB(table, order, roots, cost, lower, upper,
6591  level);
6592  if (lowerBound >= upperBound)
6593  continue;
6594  /* Impose new order. */
6595  result = ddShuffle(table, order, lower, upper);
6596  if (result == 0) goto cuddExactOutOfMem;
6597  upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
6598  /* For each top bottom variable. */
6599  for (j = level; j >= 0; j--) {
6600  /* Skip unused variables. */
6601  if (table->subtables[j+lower-1].keys == 1 &&
6602  table->vars[table->invperm[j+lower-1]]->ref == 1) continue;
6603  /* Find cost under this order. */
6604  subsetCost = cost + getLevelKeys(table, lower + level);
6605  newSubsets = updateEntry(table, order, level, subsetCost,
6606  newOrder, newCost, newSubsets, mask,
6607  lower, upper);
6608  if (j == 0)
6609  break;
6610  if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0)
6611  continue;
6612  pushDown(order,j-1,level);
6613  /* Impose new order. */
6614  result = ddShuffle(table, order, lower, upper);
6615  if (result == 0) goto cuddExactOutOfMem;
6616  upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
6617  } /* for each bottom variable */
6618  } /* for each subset of size k */
6619 
6620  /* New orders become old orders in preparation for next iteration. */
6621  tmpOrder = oldOrder; tmpCost = oldCost;
6622  oldOrder = newOrder; oldCost = newCost;
6623  newOrder = tmpOrder; newCost = tmpCost;
6624 #ifdef DD_STATS
6625  ddTotalSubsets += newSubsets;
6626 #endif
6627  oldSubsets = newSubsets;
6628  }
6629  result = ddShuffle(table, bestOrder, lower, upper);
6630  if (result == 0) goto cuddExactOutOfMem;
6631 #ifdef DD_STATS
6632  #ifdef DD_VERBOSE
6633  (void) fprintf(table->out,"\n");
6634 #endif
6635  (void) fprintf(table->out,"#:S_EXACT %8d: total subsets\n",
6636  ddTotalSubsets);
6637  (void) fprintf(table->out,"#:H_EXACT %8d: total shuffles",
6638  ddTotalShuffles);
6639 #endif
6640 
6641  freeMatrix(newOrder);
6642  freeMatrix(oldOrder);
6643  FREE(bestOrder);
6644  FREE(oldCost);
6645  FREE(newCost);
6646  FREE(symmInfo);
6647  FREE(mask);
6648  return(1);
6649 
6650  cuddExactOutOfMem:
6651 
6652  if (newOrder != NULL) freeMatrix(newOrder);
6653  if (oldOrder != NULL) freeMatrix(oldOrder);
6654  if (bestOrder != NULL) FREE(bestOrder);
6655  if (oldCost != NULL) FREE(oldCost);
6656  if (newCost != NULL) FREE(newCost);
6657  if (symmInfo != NULL) FREE(symmInfo);
6658  if (mask != NULL) FREE(mask);
6659  table->errorCode = CUDD_MEMORY_OUT;
6660  return(0);
6661 
6662 } /* end of cuddExact */
6663 
6664 
6683 static int
6685  int n)
6686 {
6687  double i, j, result;
6688 
6689  if (n < 0 || n > 33) return(-1); /* error */
6690  if (n < 2) return(1);
6691 
6692  for (result = (double)((n+3)/2), i = result+1, j=2; i <= n; i++, j++) {
6693  result *= i;
6694  result /= j;
6695  }
6696 
6697  return((int)result);
6698 
6699 } /* end of getMaxBinomial */
6700 
6701 
6702 #if 0
6703 
6715 static int
6716 gcd(
6717  int x,
6718  int y)
6719 {
6720  int a;
6721  int b;
6722  int lsbMask;
6723 
6724  /* GCD(n,0) = n. */
6725  if (x == 0) return(y);
6726  if (y == 0) return(x);
6727 
6728  a = x; b = y; lsbMask = 1;
6729 
6730  /* Here both a and b are != 0. The iteration maintains this invariant.
6731  ** Hence, we only need to check for when they become equal.
6732  */
6733  while (a != b) {
6734  if (a & lsbMask) {
6735  if (b & lsbMask) { /* both odd */
6736  if (a < b) {
6737  b = (b - a) >> 1;
6738  } else {
6739  a = (a - b) >> 1;
6740  }
6741  } else { /* a odd, b even */
6742  b >>= 1;
6743  }
6744  } else {
6745  if (b & lsbMask) { /* a even, b odd */
6746  a >>= 1;
6747  } else { /* both even */
6748  lsbMask <<= 1;
6749  }
6750  }
6751  }
6752 
6753  return(a);
6754 
6755 } /* end of gcd */
6756 #endif
6757 
6758 
6771 static DdHalfWord **
6773  int rows /* number of rows */,
6774  int cols /* number of columns */)
6775 {
6776  DdHalfWord **matrix;
6777  int i;
6778 
6779  if (cols*rows == 0) return(NULL);
6780  matrix = ALLOC(DdHalfWord *, rows);
6781  if (matrix == NULL) return(NULL);
6782  matrix[0] = ALLOC(DdHalfWord, cols*rows);
6783  if (matrix[0] == NULL) {
6784  FREE(matrix);
6785  return(NULL);
6786  }
6787  for (i = 1; i < rows; i++) {
6788  matrix[i] = matrix[i-1] + cols;
6789  }
6790  return(matrix);
6791 
6792 } /* end of getMatrix */
6793 
6794 
6806 static void
6808  DdHalfWord ** matrix)
6809 {
6810  FREE(matrix[0]);
6811  FREE(matrix);
6812  return;
6813 
6814 } /* end of freeMatrix */
6815 
6816 
6829 static int
6831  DdManager * table,
6832  int l)
6833 {
6834  int isolated;
6835  int x; /* x is an index */
6836 
6837  x = table->invperm[l];
6838  isolated = table->vars[x]->ref == 1;
6839 
6840  return(table->subtables[l].keys - isolated);
6841 
6842 } /* end of getLevelKeys */
6843 
6844 
6861 static int
6863  DdManager * table,
6864  DdHalfWord * permutation,
6865  int lower,
6866  int upper)
6867 {
6868  DdHalfWord index;
6869  int level;
6870  int position;
6871 #if 0
6872  int numvars;
6873 #endif
6874  int result;
6875 #ifdef DD_STATS
6876  unsigned long localTime;
6877  int initialSize;
6878 #ifdef DD_VERBOSE
6879  int finalSize;
6880 #endif
6881  int previousSize;
6882 #endif
6883 
6884 #ifdef DD_STATS
6885  localTime = util_cpu_time();
6886  initialSize = table->keys - table->isolated;
6887 #endif
6888 
6889 #if 0
6890  numvars = table->size;
6891 
6892  (void) fprintf(table->out,"%d:", ddTotalShuffles);
6893  for (level = 0; level < numvars; level++) {
6894  (void) fprintf(table->out," %d", table->invperm[level]);
6895  }
6896  (void) fprintf(table->out,"\n");
6897 #endif
6898 
6899  for (level = 0; level <= upper - lower; level++) {
6900  index = permutation[level];
6901  position = table->perm[index];
6902 #ifdef DD_STATS
6903  previousSize = table->keys - table->isolated;
6904 #endif
6905  result = ddSiftUp(table,position,level+lower);
6906  if (!result) return(0);
6907  }
6908 
6909 #ifdef DD_STATS
6910  ddTotalShuffles++;
6911 #ifdef DD_VERBOSE
6912  finalSize = table->keys - table->isolated;
6913  if (finalSize < initialSize) {
6914  (void) fprintf(table->out,"-");
6915  } else if (finalSize > initialSize) {
6916  (void) fprintf(table->out,"+");
6917  } else {
6918  (void) fprintf(table->out,"=");
6919  }
6920  if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n");
6921  fflush(table->out);
6922 #endif
6923 #endif
6924 
6925  return(1);
6926 
6927 } /* end of ddShuffle */
6928 
6929 
6943 static int
6945  DdManager * table,
6946  int x,
6947  int xLow)
6948 {
6949  int y;
6950  int size;
6951 
6952  y = cuddNextLow(table,x);
6953  while (y >= xLow) {
6954  size = cuddSwapInPlace(table,y,x);
6955  if (size == 0) {
6956  return(0);
6957  }
6958  x = y;
6959  y = cuddNextLow(table,x);
6960  }
6961  return(1);
6962 
6963 } /* end of ddSiftUp */
6964 
6965 
6978 static int
6980  DdManager * table,
6981  int oldBound,
6982  DdHalfWord * bestOrder,
6983  int lower,
6984  int upper)
6985 {
6986  int i;
6987  int newBound = table->keys - table->isolated;
6988 
6989  if (newBound < oldBound) {
6990 #ifdef DD_STATS
6991  (void) fprintf(table->out,"New upper bound = %d\n", newBound);
6992  fflush(table->out);
6993 #endif
6994  for (i = lower; i <= upper; i++)
6995  bestOrder[i-lower] = (DdHalfWord) table->invperm[i];
6996  return(newBound);
6997  } else {
6998  return(oldBound);
6999  }
7000 
7001 } /* end of updateUB */
7002 
7003 
7020 static int
7022  DdManager * table,
7023  int lower,
7024  int upper)
7025 {
7026  int i,j;
7027  DdNode *f;
7028  DdNodePtr *nodelist;
7029  DdNode *sentinel = &(table->sentinel);
7030  int slots;
7031  int roots = 0;
7032  int maxlevel = lower;
7033 
7034  for (i = lower; i <= upper; i++) {
7035  nodelist = table->subtables[i].nodelist;
7036  slots = table->subtables[i].slots;
7037  for (j = 0; j < slots; j++) {
7038  f = nodelist[j];
7039  while (f != sentinel) {
7040  /* A node is a root of the DAG if it cannot be
7041  ** reached by nodes above it. If a node was never
7042  ** reached during the previous depth-first searches,
7043  ** then it is a root, and we start a new depth-first
7044  ** search from it.
7045  */
7046  if (!Cudd_IsComplement(f->next)) {
7047  if (f != table->vars[f->index]) {
7048  roots++;
7049  }
7050  }
7051  if (!Cudd_IsConstant(cuddT(f))) {
7052  cuddT(f)->next = Cudd_Complement(cuddT(f)->next);
7053  if (table->perm[cuddT(f)->index] > maxlevel)
7054  maxlevel = table->perm[cuddT(f)->index];
7055  }
7056  if (!Cudd_IsConstant(cuddE(f))) {
7057  Cudd_Regular(cuddE(f))->next =
7058  Cudd_Complement(Cudd_Regular(cuddE(f))->next);
7059  if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel)
7060  maxlevel = table->perm[Cudd_Regular(cuddE(f))->index];
7061  }
7062  f = Cudd_Regular(f->next);
7063  }
7064  }
7065  }
7066  ddClearGlobal(table, lower, maxlevel);
7067 
7068  return(roots);
7069 
7070 } /* end of ddCountRoots */
7071 
7072 
7087 static void
7089  DdManager * table,
7090  int lower,
7091  int maxlevel)
7092 {
7093  int i,j;
7094  DdNode *f;
7095  DdNodePtr *nodelist;
7096  DdNode *sentinel = &(table->sentinel);
7097  int slots;
7098 
7099  for (i = lower; i <= maxlevel; i++) {
7100  nodelist = table->subtables[i].nodelist;
7101  slots = table->subtables[i].slots;
7102  for (j = 0; j < slots; j++) {
7103  f = nodelist[j];
7104  while (f != sentinel) {
7105  f->next = Cudd_Regular(f->next);
7106  f = f->next;
7107  }
7108  }
7109  }
7110 
7111 } /* end of ddClearGlobal */
7112 
7113 
7133 static int
7135  DdManager * table /* manager */,
7136  DdHalfWord * order /* optimal order for the subset */,
7137  int roots /* roots between lower and upper */,
7138  int cost /* minimum cost for the subset */,
7139  int lower /* lower level to be reordered */,
7140  int upper /* upper level to be reordered */,
7141  int level /* offset for the current top bottom var */
7142 )
7143 {
7144  int i;
7145  int lb = cost;
7146  int lb1 = 0;
7147  int lb2;
7148  int support;
7149  DdHalfWord ref;
7150 
7151  /* The levels not involved in reordering are not going to change.
7152  ** Add their sizes to the lower bound.
7153  */
7154  for (i = 0; i < lower; i++) {
7155  lb += getLevelKeys(table,i);
7156  }
7157  /* If a variable is in the support, then there is going
7158  ** to be at least one node labeled by that variable.
7159  */
7160  for (i = lower; i <= lower+level; i++) {
7161  support = table->subtables[i].keys > 1 ||
7162  table->vars[order[i-lower]]->ref > 1;
7163  lb1 += support;
7164  }
7165 
7166  /* Estimate the number of nodes required to connect the roots to
7167  ** the nodes in the bottom part. */
7168  if (lower+level+1 < table->size) {
7169  if (lower+level < upper)
7170  ref = table->vars[order[level+1]]->ref;
7171  else
7172  ref = table->vars[table->invperm[upper+1]]->ref;
7173  lb2 = table->subtables[lower+level+1].keys -
7174  (ref > (DdHalfWord) 1) - roots;
7175  } else {
7176  lb2 = 0;
7177  }
7178 
7179  lb += lb1 > lb2 ? lb1 : lb2;
7180 
7181  return(lb);
7182 
7183 } /* end of computeLB */
7184 
7185 
7200 static int
7202  DdManager * table,
7203  DdHalfWord * order,
7204  int level,
7205  int cost,
7206  DdHalfWord ** orders,
7207  int * costs,
7208  int subsets,
7209  char * mask,
7210  int lower,
7211  int upper)
7212 {
7213  int i, j;
7214  int size = upper - lower + 1;
7215 
7216  /* Build a mask that says what variables are in this subset. */
7217  for (i = lower; i <= upper; i++)
7218  mask[table->invperm[i]] = 0;
7219  for (i = level; i < size; i++)
7220  mask[order[i]] = 1;
7221 
7222  /* Check each subset until a match is found or all subsets are examined. */
7223  for (i = 0; i < subsets; i++) {
7224  DdHalfWord *subset = orders[i];
7225  for (j = level; j < size; j++) {
7226  if (mask[subset[j]] == 0)
7227  break;
7228  }
7229  if (j == size) /* no mismatches: success */
7230  break;
7231  }
7232  if (i == subsets || cost < costs[i]) { /* add or replace */
7233  for (j = 0; j < size; j++)
7234  orders[i][j] = order[j];
7235  costs[i] = cost;
7236  subsets += (i == subsets);
7237  }
7238  return(subsets);
7239 
7240 } /* end of updateEntry */
7241 
7242 
7254 static void
7256  DdHalfWord * order,
7257  int j,
7258  int level)
7259 {
7260  int i;
7261  DdHalfWord tmp;
7262 
7263  tmp = order[j];
7264  for (i = j; i < level; i++) {
7265  order[i] = order[i+1];
7266  }
7267  order[level] = tmp;
7268  return;
7269 
7270 } /* end of pushDown */
7271 
7272 
7292 static DdHalfWord *
7294  DdManager * table,
7295  int lower,
7296  int upper)
7297 {
7298  int level, index, next, nextindex;
7299  DdHalfWord *symmInfo;
7300 
7301  symmInfo = ALLOC(DdHalfWord, table->size);
7302  if (symmInfo == NULL) return(NULL);
7303 
7304  for (level = lower; level <= upper; level++) {
7305  index = table->invperm[level];
7306  next = table->subtables[level].next;
7307  nextindex = table->invperm[next];
7308  symmInfo[index] = nextindex;
7309  }
7310  return(symmInfo);
7311 
7312 } /* end of initSymmInfo */
7313 
7314 
7328 static int
7330  DdManager * table,
7331  DdHalfWord * symmInfo,
7332  int index,
7333  int level)
7334 {
7335  int i;
7336 
7337  i = symmInfo[index];
7338  while (i != index) {
7339  if (index < i && table->perm[i] <= level)
7340  return(0);
7341  i = symmInfo[i];
7342  }
7343  return(1);
7344 
7345 } /* end of checkSymmInfo */
7346 
7347 
7431 /*---------------------------------------------------------------------------*/
7432 /* Constant declarations */
7433 /*---------------------------------------------------------------------------*/
7434 
7435 /*---------------------------------------------------------------------------*/
7436 /* Stucture declarations */
7437 /*---------------------------------------------------------------------------*/
7438 
7439 /*---------------------------------------------------------------------------*/
7440 /* Type declarations */
7441 /*---------------------------------------------------------------------------*/
7442 
7443 /*---------------------------------------------------------------------------*/
7444 /* Variable declarations */
7445 /*---------------------------------------------------------------------------*/
7446 
7447 //#ifndef lint
7448 //static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.30 2012/02/05 01:07:18 fabio Exp $";
7449 //#endif
7450 
7451 static int popsize; /* the size of the population */
7452 static int numvars; /* the number of input variables in the ckt. */
7453 /* storedd stores the population orders and sizes. This table has two
7454 ** extra rows and one extras column. The two extra rows are used for the
7455 ** offspring produced by a crossover. Each row stores one order and its
7456 ** size. The order is stored by storing the indices of variables in the
7457 ** order in which they appear in the order. The table is in reality a
7458 ** one-dimensional array which is accessed via a macro to give the illusion
7459 ** it is a two-dimensional structure.
7460 */
7461 static int *storedd;
7462 static st_table *computed; /* hash table to identify existing orders */
7463 static int *repeat; /* how many times an order is present */
7464 static int large; /* stores the index of the population with
7465  ** the largest number of nodes in the DD */
7466 static int result;
7467 static int cross; /* the number of crossovers to perform */
7468 
7469 /*---------------------------------------------------------------------------*/
7470 /* Macro declarations */
7471 /*---------------------------------------------------------------------------*/
7472 
7473 /* macro used to access the population table as if it were a
7474 ** two-dimensional structure.
7475 */
7476 #define STOREDD(i,j) storedd[(i)*(numvars+1)+(j)]
7477 
7478 #ifdef __cplusplus
7479 extern "C" {
7480 #endif
7481 
7484 /*---------------------------------------------------------------------------*/
7485 /* Static function prototypes */
7486 /*---------------------------------------------------------------------------*/
7487 
7488 static int make_random (DdManager *table, int lower);
7489 static int sift_up (DdManager *table, int x, int x_low);
7490 static int build_dd (DdManager *table, int num, int lower, int upper);
7491 static int largest (void);
7492 static int rand_int (int a);
7493 static int array_hash (char *array, int modulus);
7494 static int array_compare (const char *array1, const char *array2);
7495 static int find_best (void);
7496 #ifdef DD_STATS
7497 static double find_average_fitness (void);
7498 #endif
7499 static int PMX (int maxvar);
7500 static int roulette (int *p1, int *p2);
7501 
7504 #ifdef __cplusplus
7505 }
7506 #endif
7507 
7508 /*---------------------------------------------------------------------------*/
7509 /* Definition of exported functions */
7510 /*---------------------------------------------------------------------------*/
7511 
7512 /*---------------------------------------------------------------------------*/
7513 /* Definition of internal functions */
7514 /*---------------------------------------------------------------------------*/
7515 
7516 
7532 int
7534  DdManager * table /* manager */,
7535  int lower /* lowest level to be reordered */,
7536  int upper /* highest level to be reorderded */)
7537 {
7538  int i,n,m; /* dummy/loop vars */
7539  int index;
7540 #ifdef DD_STATS
7541  double average_fitness;
7542 #endif
7543  int small; /* index of smallest DD in population */
7544 
7545  /* Do an initial sifting to produce at least one reasonable individual. */
7546  if (!cuddSifting(table,lower,upper)) return(0);
7547 
7548  /* Get the initial values. */
7549  numvars = upper - lower + 1; /* number of variables to be reordered */
7550  if (table->populationSize == 0) {
7551  popsize = 3 * numvars; /* population size is 3 times # of vars */
7552  if (popsize > 120) {
7553  popsize = 120; /* Maximum population size is 120 */
7554  }
7555  } else {
7556  popsize = table->populationSize; /* user specified value */
7557  }
7558  if (popsize < 4) popsize = 4; /* enforce minimum population size */
7559 
7560  /* Allocate population table. */
7561  storedd = ALLOC(int,(popsize+2)*(numvars+1));
7562  if (storedd == NULL) {
7563  table->errorCode = CUDD_MEMORY_OUT;
7564  return(0);
7565  }
7566 
7567  /* Initialize the computed table. This table is made up of two data
7568  ** structures: A hash table with the key given by the order, which says
7569  ** if a given order is present in the population; and the repeat
7570  ** vector, which says how many copies of a given order are stored in
7571  ** the population table. If there are multiple copies of an order, only
7572  ** one has a repeat count greater than 1. This copy is the one pointed
7573  ** by the computed table.
7574  */
7575  repeat = ALLOC(int,popsize);
7576  if (repeat == NULL) {
7577  table->errorCode = CUDD_MEMORY_OUT;
7578  FREE(storedd);
7579  return(0);
7580  }
7581  for (i = 0; i < popsize; i++) {
7582  repeat[i] = 0;
7583  }
7585  if (computed == NULL) {
7586  table->errorCode = CUDD_MEMORY_OUT;
7587  FREE(storedd);
7588  FREE(repeat);
7589  return(0);
7590  }
7591 
7592  /* Copy the current DD and its size to the population table. */
7593  for (i = 0; i < numvars; i++) {
7594  STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */
7595  }
7596  STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */
7597 
7598  /* Store the initial order in the computed table. */
7599  if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) {
7600  FREE(storedd);
7601  FREE(repeat);
7602  st_free_table(computed);
7603  return(0);
7604  }
7605  repeat[0]++;
7606 
7607  /* Insert the reverse order as second element of the population. */
7608  for (i = 0; i < numvars; i++) {
7609  STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */
7610  }
7611 
7612  /* Now create the random orders. make_random fills the population
7613  ** table with random permutations. The successive loop builds and sifts
7614  ** the DDs for the reverse order and each random permutation, and stores
7615  ** the results in the computed table.
7616  */
7617  if (!make_random(table,lower)) {
7618  table->errorCode = CUDD_MEMORY_OUT;
7619  FREE(storedd);
7620  FREE(repeat);
7621  st_free_table(computed);
7622  return(0);
7623  }
7624  for (i = 1; i < popsize; i++) {
7625  result = build_dd(table,i,lower,upper); /* build and sift order */
7626  if (!result) {
7627  FREE(storedd);
7628  FREE(repeat);
7629  st_free_table(computed);
7630  return(0);
7631  }
7632  if (st_lookup_int(computed,(char *)&STOREDD(i,0),&index)) {
7633  repeat[index]++;
7634  } else {
7635  if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) ==
7636  ST_OUT_OF_MEM) {
7637  FREE(storedd);
7638  FREE(repeat);
7639  st_free_table(computed);
7640  return(0);
7641  }
7642  repeat[i]++;
7643  }
7644  }
7645 
7646 #if 0
7647  #ifdef DD_STATS
7648  /* Print the initial population. */
7649  (void) fprintf(table->out,"Initial population after sifting\n");
7650  for (m = 0; m < popsize; m++) {
7651  for (i = 0; i < numvars; i++) {
7652  (void) fprintf(table->out," %2d",STOREDD(m,i));
7653  }
7654  (void) fprintf(table->out," : %3d (%d)\n",
7655  STOREDD(m,numvars),repeat[m]);
7656  }
7657 #endif
7658 #endif
7659 
7660  small = find_best();
7661 #ifdef DD_STATS
7662  average_fitness = find_average_fitness();
7663  (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
7664 #endif
7665 
7666  /* Decide how many crossovers should be tried. */
7667  if (table->numberXovers == 0) {
7668  cross = 3*numvars;
7669  if (cross > 60) { /* do a maximum of 50 crossovers */
7670  cross = 60;
7671  }
7672  } else {
7673  cross = table->numberXovers; /* use user specified value */
7674  }
7675  if (cross >= popsize) {
7676  cross = popsize;
7677  }
7678 
7679  /* Perform the crossovers to get the best order. */
7680  for (m = 0; m < cross; m++) {
7681  if (!PMX(table->size)) { /* perform one crossover */
7682  table->errorCode = CUDD_MEMORY_OUT;
7683  FREE(storedd);
7684  FREE(repeat);
7685  st_free_table(computed);
7686  return(0);
7687  }
7688  /* The offsprings are left in the last two entries of the
7689  ** population table. These are now considered in turn.
7690  */
7691  for (i = popsize; i <= popsize+1; i++) {
7692  result = build_dd(table,i,lower,upper); /* build and sift child */
7693  if (!result) {
7694  FREE(storedd);
7695  FREE(repeat);
7696  st_free_table(computed);
7697  return(0);
7698  }
7699  large = largest(); /* find the largest DD in population */
7700 
7701  /* If the new child is smaller than the largest DD in the current
7702  ** population, enter it into the population in place of the
7703  ** largest DD.
7704  */
7705  if (STOREDD(i,numvars) < STOREDD(large,numvars)) {
7706  /* Look up the largest DD in the computed table.
7707  ** Decrease its repetition count. If the repetition count
7708  ** goes to 0, remove the largest DD from the computed table.
7709  */
7710  result = st_lookup_int(computed,(char *)&STOREDD(large,0),
7711  &index);
7712  if (!result) {
7713  FREE(storedd);
7714  FREE(repeat);
7715  st_free_table(computed);
7716  return(0);
7717  }
7718  repeat[index]--;
7719  if (repeat[index] == 0) {
7720  int *pointer = &STOREDD(index,0);
7721  result = st_delete(computed, &pointer, NULL);
7722  if (!result) {
7723  FREE(storedd);
7724  FREE(repeat);
7725  st_free_table(computed);
7726  return(0);
7727  }
7728  }
7729  /* Copy the new individual to the entry of the
7730  ** population table just made available and update the
7731  ** computed table.
7732  */
7733  for (n = 0; n <= numvars; n++) {
7734  STOREDD(large,n) = STOREDD(i,n);
7735  }
7736  if (st_lookup_int(computed,(char *)&STOREDD(large,0),
7737  &index)) {
7738  repeat[index]++;
7739  } else {
7740  if (st_insert(computed,(char *)&STOREDD(large,0),
7741  (char *)(long)large) == ST_OUT_OF_MEM) {
7742  FREE(storedd);
7743  FREE(repeat);
7744  st_free_table(computed);
7745  return(0);
7746  }
7747  repeat[large]++;
7748  }
7749  }
7750  }
7751  }
7752 
7753  /* Find the smallest DD in the population and build it;
7754  ** that will be the result.
7755  */
7756  small = find_best();
7757 
7758  /* Print stats on the final population. */
7759 #ifdef DD_STATS
7760  average_fitness = find_average_fitness();
7761  (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
7762 #endif
7763 
7764  /* Clean up, build the result DD, and return. */
7765  st_free_table(computed);
7766  computed = NULL;
7767  result = build_dd(table,small,lower,upper);
7768  FREE(storedd);
7769  FREE(repeat);
7770  return(result);
7771 
7772 } /* end of cuddGa */
7773 
7774 
7775 /*---------------------------------------------------------------------------*/
7776 /* Definition of static functions */
7777 /*---------------------------------------------------------------------------*/
7778 
7792 static int
7794  DdManager * table,
7795  int lower)
7796 {
7797  int i,j; /* loop variables */
7798  int *used; /* is a number already in a permutation */
7799  int next; /* next random number without repetitions */
7800 
7801  used = ALLOC(int,numvars);
7802  if (used == NULL) {
7803  table->errorCode = CUDD_MEMORY_OUT;
7804  return(0);
7805  }
7806 #if 0
7807  #ifdef DD_STATS
7808  (void) fprintf(table->out,"Initial population before sifting\n");
7809  for (i = 0; i < 2; i++) {
7810  for (j = 0; j < numvars; j++) {
7811  (void) fprintf(table->out," %2d",STOREDD(i,j));
7812  }
7813  (void) fprintf(table->out,"\n");
7814  }
7815 #endif
7816 #endif
7817  for (i = 2; i < popsize; i++) {
7818  for (j = 0; j < numvars; j++) {
7819  used[j] = 0;
7820  }
7821  /* Generate a permutation of {0...numvars-1} and use it to
7822  ** permute the variables in the layesr from lower to upper.
7823  */
7824  for (j = 0; j < numvars; j++) {
7825  do {
7826  next = rand_int(numvars-1);
7827  } while (used[next] != 0);
7828  used[next] = 1;
7829  STOREDD(i,j) = table->invperm[next+lower];
7830  }
7831 #if 0
7832  #ifdef DD_STATS
7833  /* Print the order just generated. */
7834  for (j = 0; j < numvars; j++) {
7835  (void) fprintf(table->out," %2d",STOREDD(i,j));
7836  }
7837  (void) fprintf(table->out,"\n");
7838 #endif
7839 #endif
7840  }
7841  FREE(used);
7842  return(1);
7843 
7844 } /* end of make_random */
7845 
7846 
7860 static int
7862  DdManager * table,
7863  int x,
7864  int x_low)
7865 {
7866  int y;
7867  int size;
7868 
7869  y = cuddNextLow(table,x);
7870  while (y >= x_low) {
7871  size = cuddSwapInPlace(table,y,x);
7872  if (size == 0) {
7873  return(0);
7874  }
7875  x = y;
7876  y = cuddNextLow(table,x);
7877  }
7878  return(1);
7879 
7880 } /* end of sift_up */
7881 
7882 
7896 static int
7898  DdManager * table,
7899  int num /* the index of the individual to be built */,
7900  int lower,
7901  int upper)
7902 {
7903  int i,j; /* loop vars */
7904  int position;
7905  int index;
7906  int limit; /* how large the DD for this order can grow */
7907  int size;
7908 
7909  /* Check the computed table. If the order already exists, it
7910  ** suffices to copy the size from the existing entry.
7911  */
7912  if (computed && st_lookup_int(computed,(char *)&STOREDD(num,0),&index)) {
7913  STOREDD(num,numvars) = STOREDD(index,numvars);
7914 #ifdef DD_STATS
7915  (void) fprintf(table->out,"\nCache hit for index %d", index);
7916 #endif
7917  return(1);
7918  }
7919 
7920  /* Stop if the DD grows 20 times larges than the reference size. */
7921  limit = 20 * STOREDD(0,numvars);
7922 
7923  /* Sift up the variables so as to build the desired permutation.
7924  ** First the variable that has to be on top is sifted to the top.
7925  ** Then the variable that has to occupy the secon position is sifted
7926  ** up to the second position, and so on.
7927  */
7928  for (j = 0; j < numvars; j++) {
7929  i = STOREDD(num,j);
7930  position = table->perm[i];
7931  result = sift_up(table,position,j+lower);
7932  if (!result) return(0);
7933  size = table->keys - table->isolated;
7934  if (size > limit) break;
7935  }
7936 
7937  /* Sift the DD just built. */
7938 #ifdef DD_STATS
7939  (void) fprintf(table->out,"\n");
7940 #endif
7941  result = cuddSifting(table,lower,upper);
7942  if (!result) return(0);
7943 
7944  /* Copy order and size to table. */
7945  for (j = 0; j < numvars; j++) {
7946  STOREDD(num,j) = table->invperm[lower+j];
7947  }
7948  STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */
7949  return(1);
7950 
7951 } /* end of build_dd */
7952 
7953 
7967 static int
7968 largest(void)
7969 {
7970  int i; /* loop var */
7971  int big; /* temporary holder to return result */
7972 
7973  big = 0;
7974  while (repeat[big] > 1) big++;
7975  for (i = big + 1; i < popsize; i++) {
7976  if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) {
7977  big = i;
7978  }
7979  }
7980  return(big);
7981 
7982 } /* end of largest */
7983 
7984 
7996 static int
7998  int a)
7999 {
8000  return(Cudd_Random() % (a+1));
8001 
8002 } /* end of rand_int */
8003 
8004 
8017 static int
8019  char * array,
8020  int modulus)
8021 {
8022  int val = 0;
8023  int i;
8024  int *intarray;
8025 
8026  intarray = (int *) array;
8027 
8028  for (i = 0; i < numvars; i++) {
8029  val = val * 997 + intarray[i];
8030  }
8031 
8032  return ((val < 0) ? -val : val) % modulus;
8033 
8034 } /* end of array_hash */
8035 
8036 
8049 static int
8051  const char * array1,
8052  const char * array2)
8053 {
8054  int i;
8055  int *intarray1, *intarray2;
8056 
8057  intarray1 = (int *) array1;
8058  intarray2 = (int *) array2;
8059 
8060  for (i = 0; i < numvars; i++) {
8061  if (intarray1[i] != intarray2[i]) return(1);
8062  }
8063  return(0);
8064 
8065 } /* end of array_compare */
8066 
8067 
8079 static int
8081 {
8082  int i,small;
8083 
8084  small = 0;
8085  for (i = 1; i < popsize; i++) {
8086  if (STOREDD(i,numvars) < STOREDD(small,numvars)) {
8087  small = i;
8088  }
8089  }
8090  return(small);
8091 
8092 } /* end of find_best */
8093 
8094 
8106 #ifdef DD_STATS
8107 static double
8108 find_average_fitness(void)
8109 {
8110  int i;
8111  int total_fitness = 0;
8112  double average_fitness;
8113 
8114  for (i = 0; i < popsize; i++) {
8115  total_fitness += STOREDD(i,numvars);
8116  }
8117  average_fitness = (double) total_fitness / (double) popsize;
8118  return(average_fitness);
8119 
8120 } /* end of find_average_fitness */
8121 #endif
8122 
8123 
8137 static int
8139  int maxvar)
8140 {
8141  int cut1,cut2; /* the two cut positions (random) */
8142  int mom,dad; /* the two randomly chosen parents */
8143  int *inv1; /* inverse permutations for repair algo */
8144  int *inv2;
8145  int i; /* loop vars */
8146  int u,v; /* aux vars */
8147 
8148  inv1 = ALLOC(int,maxvar);
8149  if (inv1 == NULL) {
8150  return(0);
8151  }
8152  inv2 = ALLOC(int,maxvar);
8153  if (inv2 == NULL) {
8154  FREE(inv1);
8155  return(0);
8156  }
8157 
8158  /* Choose two orders from the population using roulette wheel. */
8159  if (!roulette(&mom,&dad)) {
8160  FREE(inv1);
8161  FREE(inv2);
8162  return(0);
8163  }
8164 
8165  /* Choose two random cut positions. A cut in position i means that
8166  ** the cut immediately precedes position i. If cut1 < cut2, we
8167  ** exchange the middle of the two orderings; otherwise, we
8168  ** exchange the beginnings and the ends.
8169  */
8170  cut1 = rand_int(numvars-1);
8171  do {
8172  cut2 = rand_int(numvars-1);
8173  } while (cut1 == cut2);
8174 
8175 #if 0
8176  /* Print out the parents. */
8177  (void) fprintf(table->out,
8178  "Crossover of %d (mom) and %d (dad) between %d and %d\n",
8179  mom,dad,cut1,cut2);
8180  for (i = 0; i < numvars; i++) {
8181  if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
8182  (void) fprintf(table->out,"%2d ",STOREDD(mom,i));
8183  }
8184  (void) fprintf(table->out,"\n");
8185  for (i = 0; i < numvars; i++) {
8186  if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
8187  (void) fprintf(table->out,"%2d ",STOREDD(dad,i));
8188  }
8189  (void) fprintf(table->out,"\n");
8190 #endif
8191 
8192  /* Initialize the inverse permutations: -1 means yet undetermined. */
8193  for (i = 0; i < maxvar; i++) {
8194  inv1[i] = -1;
8195  inv2[i] = -1;
8196  }
8197 
8198  /* Copy the portions whithin the cuts. */
8199  for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) {
8200  STOREDD(popsize,i) = STOREDD(dad,i);
8201  inv1[STOREDD(popsize,i)] = i;
8202  STOREDD(popsize+1,i) = STOREDD(mom,i);
8203  inv2[STOREDD(popsize+1,i)] = i;
8204  }
8205 
8206  /* Now apply the repair algorithm outside the cuts. */
8207  for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) {
8208  v = i;
8209  do {
8210  u = STOREDD(mom,v);
8211  v = inv1[u];
8212  } while (v != -1);
8213  STOREDD(popsize,i) = u;
8214  inv1[u] = i;
8215  v = i;
8216  do {
8217  u = STOREDD(dad,v);
8218  v = inv2[u];
8219  } while (v != -1);
8220  STOREDD(popsize+1,i) = u;
8221  inv2[u] = i;
8222  }
8223 
8224 #if 0
8225  /* Print the results of crossover. */
8226  for (i = 0; i < numvars; i++) {
8227  if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
8228  (void) fprintf(table->out,"%2d ",STOREDD(popsize,i));
8229  }
8230  (void) fprintf(table->out,"\n");
8231  for (i = 0; i < numvars; i++) {
8232  if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
8233  (void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i));
8234  }
8235  (void) fprintf(table->out,"\n");
8236 #endif
8237 
8238  FREE(inv1);
8239  FREE(inv2);
8240  return(1);
8241 
8242 } /* end of PMX */
8243 
8244 
8257 static int
8259  int * p1,
8260  int * p2)
8261 {
8262  double *wheel;
8263  double spin;
8264  int i;
8265 
8266  wheel = ALLOC(double,popsize);
8267  if (wheel == NULL) {
8268  return(0);
8269  }
8270 
8271  /* The fitness of an individual is the reciprocal of its size. */
8272  wheel[0] = 1.0 / (double) STOREDD(0,numvars);
8273 
8274  for (i = 1; i < popsize; i++) {
8275  wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars);
8276  }
8277 
8278  /* Get a random number between 0 and wheel[popsize-1] (that is,
8279  ** the sum of all fitness values. 2147483561 is the largest number
8280  ** returned by Cudd_Random.
8281  */
8282  spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0;
8283 
8284  /* Find the lucky element by scanning the wheel. */
8285  for (i = 0; i < popsize; i++) {
8286  if (spin <= wheel[i]) break;
8287  }
8288  *p1 = i;
8289 
8290  /* Repeat the process for the second parent, making sure it is
8291  ** distinct from the first.
8292  */
8293  do {
8294  spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0;
8295  for (i = 0; i < popsize; i++) {
8296  if (spin <= wheel[i]) break;
8297  }
8298  } while (i == *p1);
8299  *p2 = i;
8300 
8301  FREE(wheel);
8302  return(1);
8303 
8304 } /* end of roulette */
8305 
8386 /*---------------------------------------------------------------------------*/
8387 /* Constant declarations */
8388 /*---------------------------------------------------------------------------*/
8389 
8390 /* Constants for lazy sifting */
8391 #define DD_NORMAL_SIFT 0
8392 #define DD_LAZY_SIFT 1
8393 
8394 /* Constants for sifting up and down */
8395 #define DD_SIFT_DOWN 0
8396 #define DD_SIFT_UP 1
8397 
8398 /*---------------------------------------------------------------------------*/
8399 /* Stucture declarations */
8400 /*---------------------------------------------------------------------------*/
8401 
8402 /*---------------------------------------------------------------------------*/
8403 /* Type declarations */
8404 /*---------------------------------------------------------------------------*/
8405 
8406 #ifdef __cplusplus
8407 extern "C" {
8408 #endif
8409 typedef int (*DD_CHKFP)(DdManager *, int, int);
8410 #ifdef __cplusplus
8411 }
8412 #endif
8413 
8414 /*---------------------------------------------------------------------------*/
8415 /* Variable declarations */
8416 /*---------------------------------------------------------------------------*/
8417 
8418 //#ifndef lint
8419 //static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.49 2012/02/05 01:07:18 fabio Exp $";
8420 //#endif
8421 
8422 static int *entry;
8423 extern int ddTotalNumberSwapping;
8424 #ifdef DD_STATS
8425 extern int ddTotalNISwaps;
8426 static int extsymmcalls;
8427 static int extsymm;
8428 static int secdiffcalls;
8429 static int secdiff;
8430 static int secdiffmisfire;
8431 #endif
8432 #ifdef DD_DEBUG
8433 static int pr = 0; /* flag to enable printing while debugging */
8434  /* by depositing a 1 into it */
8435 #endif
8436 static unsigned int originalSize;
8437 
8438 /*---------------------------------------------------------------------------*/
8439 /* Macro declarations */
8440 /*---------------------------------------------------------------------------*/
8441 
8442 #ifdef __cplusplus
8443 extern "C" {
8444 #endif
8445 
8448 /*---------------------------------------------------------------------------*/
8449 /* Static function prototypes */
8450 /*---------------------------------------------------------------------------*/
8451 
8452 static int ddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
8453 #ifdef DD_STATS
8454 static int ddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
8455 #endif
8456 static int ddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
8457 static void ddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
8458 static int ddUniqueCompareGroup (int *ptrX, int *ptrY);
8459 static int ddGroupSifting (DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag);
8460 static void ddCreateGroup (DdManager *table, int x, int y);
8461 static int ddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag);
8462 static int ddGroupSiftingUp (DdManager *table, int y, int xLow, DD_CHKFP checkFunction, Move **moves);
8463 static int ddGroupSiftingDown (DdManager *table, int x, int xHigh, DD_CHKFP checkFunction, Move **moves);
8464 static int ddGroupMove (DdManager *table, int x, int y, Move **moves);
8465 static int ddGroupMoveBackward (DdManager *table, int x, int y);
8466 static int ddGroupSiftingBackward (DdManager *table, Move *moves, int size, int upFlag, int lazyFlag);
8467 static void ddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
8468 static void ddDissolveGroup (DdManager *table, int x, int y);
8469 static int ddNoCheck (DdManager *table, int x, int y);
8470 static int ddSecDiffCheck (DdManager *table, int x, int y);
8471 static int ddExtSymmCheck (DdManager *table, int x, int y);
8472 static int ddVarGroupCheck (DdManager * table, int x, int y);
8473 static int ddSetVarHandled (DdManager *dd, int index);
8474 static int ddResetVarHandled (DdManager *dd, int index);
8475 static int ddIsVarHandled (DdManager *dd, int index);
8476 
8479 #ifdef __cplusplus
8480 }
8481 #endif
8482 
8483 /*---------------------------------------------------------------------------*/
8484 /* Definition of exported functions */
8485 /*---------------------------------------------------------------------------*/
8486 
8487 
8488 
8489 /*---------------------------------------------------------------------------*/
8490 /* Definition of internal functions */
8491 /*---------------------------------------------------------------------------*/
8492 
8493 
8506 int
8508  DdManager * table /* DD table */,
8509  Cudd_ReorderingType method /* reordering method for the groups of leaves */)
8510 {
8511  int i;
8512  int nvars;
8513  int result;
8514  int tempTree;
8515 
8516  /* If no tree is provided we create a temporary one in which all
8517  ** variables are in a single group. After reordering this tree is
8518  ** destroyed.
8519  */
8520  tempTree = table->tree == NULL;
8521  if (tempTree) {
8522  table->tree = Mtr_InitGroupTree(0,table->size);
8523  table->tree->index = table->invperm[0];
8524  }
8525  nvars = table->size;
8526 
8527 #ifdef DD_DEBUG
8528  if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:");
8529  Mtr_PrintGroups(table->tree,pr <= 0);
8530 #endif
8531 
8532 #ifdef DD_STATS
8533  extsymmcalls = 0;
8534  extsymm = 0;
8535  secdiffcalls = 0;
8536  secdiff = 0;
8537  secdiffmisfire = 0;
8538 
8539  (void) fprintf(table->out,"\n");
8540  if (!tempTree)
8541  (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n",
8542  ddCountInternalMtrNodes(table,table->tree));
8543 #endif
8544 
8545  /* Initialize the group of each subtable to itself. Initially
8546  ** there are no groups. Groups are created according to the tree
8547  ** structure in postorder fashion.
8548  */
8549  for (i = 0; i < nvars; i++)
8550  table->subtables[i].next = i;
8551 
8552 
8553  /* Reorder. */
8554  result = ddTreeSiftingAux(table, table->tree, method);
8555 
8556 #ifdef DD_STATS /* print stats */
8557  if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
8558  (table->groupcheck == CUDD_GROUP_CHECK7 ||
8559  table->groupcheck == CUDD_GROUP_CHECK5)) {
8560  (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
8561  (void) fprintf(table->out,"extsymm = %d",extsymm);
8562  }
8563  if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
8564  table->groupcheck == CUDD_GROUP_CHECK7) {
8565  (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
8566  (void) fprintf(table->out,"secdiff = %d\n",secdiff);
8567  (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
8568  }
8569 #endif
8570 
8571  if (tempTree)
8572  Cudd_FreeTree(table);
8573  else
8574  Mtr_ReorderGroups(table->tree, table->perm);
8575 
8576  return(result);
8577 
8578 } /* end of cuddTreeSifting */
8579 
8580 
8581 /*---------------------------------------------------------------------------*/
8582 /* Definition of static functions */
8583 /*---------------------------------------------------------------------------*/
8584 
8585 
8596 static int
8598  DdManager * table,
8599  MtrNode * treenode,
8600  Cudd_ReorderingType method)
8601 {
8602  MtrNode *auxnode;
8603  int res;
8604  Cudd_AggregationType saveCheck;
8605 
8606 #ifdef DD_DEBUG
8607  Mtr_PrintGroups(treenode,1);
8608 #endif
8609 
8610  auxnode = treenode;
8611  while (auxnode != NULL) {
8612  if (auxnode->child != NULL) {
8613  if (!ddTreeSiftingAux(table, auxnode->child, method))
8614  return(0);
8615  saveCheck = table->groupcheck;
8616  table->groupcheck = CUDD_NO_CHECK;
8617  if (method != CUDD_REORDER_LAZY_SIFT)
8618  res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
8619  else
8620  res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT);
8621  table->groupcheck = saveCheck;
8622 
8623  if (res == 0)
8624  return(0);
8625  } else if (auxnode->size > 1) {
8626  if (!ddReorderChildren(table, auxnode, method))
8627  return(0);
8628  }
8629  auxnode = auxnode->younger;
8630  }
8631 
8632  return(1);
8633 
8634 } /* end of ddTreeSiftingAux */
8635 
8636 
8637 #ifdef DD_STATS
8638 
8648 static int
8649 ddCountInternalMtrNodes(
8650  DdManager * table,
8651  MtrNode * treenode)
8652 {
8653  MtrNode *auxnode;
8654  int count,nodeCount;
8655 
8656 
8657  nodeCount = 0;
8658  auxnode = treenode;
8659  while (auxnode != NULL) {
8660  if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
8661  nodeCount++;
8662  count = ddCountInternalMtrNodes(table,auxnode->child);
8663  nodeCount += count;
8664  }
8665  auxnode = auxnode->younger;
8666  }
8667 
8668  return(nodeCount);
8669 
8670 } /* end of ddCountInternalMtrNodes */
8671 #endif
8672 
8673 
8688 static int
8690  DdManager * table,
8691  MtrNode * treenode,
8692  Cudd_ReorderingType method)
8693 {
8694  int lower;
8695  int upper;
8696  int result;
8697  unsigned int initialSize;
8698 
8699  ddFindNodeHiLo(table,treenode,&lower,&upper);
8700  /* If upper == -1 these variables do not exist yet. */
8701  if (upper == -1)
8702  return(1);
8703 
8704  if (treenode->flags == MTR_FIXED) {
8705  result = 1;
8706  } else {
8707 #ifdef DD_STATS
8708  (void) fprintf(table->out," ");
8709 #endif
8710  switch (method) {
8711  case CUDD_REORDER_RANDOM:
8713  result = cuddSwapping(table,lower,upper,method);
8714  break;
8715  case CUDD_REORDER_SIFT:
8716  result = cuddSifting(table,lower,upper);
8717  break;
8719  do {
8720  initialSize = table->keys - table->isolated;
8721  result = cuddSifting(table,lower,upper);
8722  if (initialSize <= table->keys - table->isolated)
8723  break;
8724 #ifdef DD_STATS
8725  else
8726  (void) fprintf(table->out,"\n");
8727 #endif
8728  } while (result != 0);
8729  break;
8731  result = cuddSymmSifting(table,lower,upper);
8732  break;
8734  result = cuddSymmSiftingConv(table,lower,upper);
8735  break;
8737  if (table->groupcheck == CUDD_NO_CHECK) {
8738  result = ddGroupSifting(table,lower,upper,ddNoCheck,
8739  DD_NORMAL_SIFT);
8740  } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
8741  result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
8742  DD_NORMAL_SIFT);
8743  } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
8744  result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
8745  DD_NORMAL_SIFT);
8746  } else {
8747  (void) fprintf(table->err,
8748  "Unknown group ckecking method\n");
8749  result = 0;
8750  }
8751  break;
8753  do {
8754  initialSize = table->keys - table->isolated;
8755  if (table->groupcheck == CUDD_NO_CHECK) {
8756  result = ddGroupSifting(table,lower,upper,ddNoCheck,
8757  DD_NORMAL_SIFT);
8758  } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
8759  result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
8760  DD_NORMAL_SIFT);
8761  } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
8762  result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
8763  DD_NORMAL_SIFT);
8764  } else {
8765  (void) fprintf(table->err,
8766  "Unknown group ckecking method\n");
8767  result = 0;
8768  }
8769 #ifdef DD_STATS
8770  (void) fprintf(table->out,"\n");
8771 #endif
8772  result = cuddWindowReorder(table,lower,upper,
8774  if (initialSize <= table->keys - table->isolated)
8775  break;
8776 #ifdef DD_STATS
8777  else
8778  (void) fprintf(table->out,"\n");
8779 #endif
8780  } while (result != 0);
8781  break;
8782  case CUDD_REORDER_WINDOW2:
8783  case CUDD_REORDER_WINDOW3:
8784  case CUDD_REORDER_WINDOW4:
8788  result = cuddWindowReorder(table,lower,upper,method);
8789  break;
8791  result = cuddAnnealing(table,lower,upper);
8792  break;
8793  case CUDD_REORDER_GENETIC:
8794  result = cuddGa(table,lower,upper);
8795  break;
8796  case CUDD_REORDER_LINEAR:
8797  result = cuddLinearAndSifting(table,lower,upper);
8798  break;
8800  do {
8801  initialSize = table->keys - table->isolated;
8802  result = cuddLinearAndSifting(table,lower,upper);
8803  if (initialSize <= table->keys - table->isolated)
8804  break;
8805 #ifdef DD_STATS
8806  else
8807  (void) fprintf(table->out,"\n");
8808 #endif
8809  } while (result != 0);
8810  break;
8811  case CUDD_REORDER_EXACT:
8812  result = cuddExact(table,lower,upper);
8813  break;
8815  result = ddGroupSifting(table,lower,upper,ddVarGroupCheck,
8816  DD_LAZY_SIFT);
8817  break;
8818  default:
8819  return(0);
8820  }
8821  }
8822 
8823  /* Create a single group for all the variables that were sifted,
8824  ** so that they will be treated as a single block by successive
8825  ** invocations of ddGroupSifting.
8826  */
8827  ddMergeGroups(table,treenode,lower,upper);
8828 
8829 #ifdef DD_DEBUG
8830  if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:");
8831 #endif
8832 
8833  return(result);
8834 
8835 } /* end of ddReorderChildren */
8836 
8837 
8852 static void
8854  DdManager * table,
8855  MtrNode * treenode,
8856  int * lower,
8857  int * upper)
8858 {
8859  int low;
8860  int high;
8861 
8862  /* Check whether no variables in this group already exist.
8863  ** If so, return immediately. The calling procedure will know from
8864  ** the values of upper that no reordering is needed.
8865  */
8866  if ((int) treenode->low >= table->size) {
8867  *lower = table->size;
8868  *upper = -1;
8869  return;
8870  }
8871 
8872  *lower = low = (unsigned int) table->perm[treenode->index];
8873  high = (int) (low + treenode->size - 1);
8874 
8875  if (high >= table->size) {
8876  /* This is the case of a partially existing group. The aim is to
8877  ** reorder as many variables as safely possible. If the tree
8878  ** node is terminal, we just reorder the subset of the group
8879  ** that is currently in existence. If the group has
8880  ** subgroups, then we only reorder those subgroups that are
8881  ** fully instantiated. This way we avoid breaking up a group.
8882  */
8883  MtrNode *auxnode = treenode->child;
8884  if (auxnode == NULL) {
8885  *upper = (unsigned int) table->size - 1;
8886  } else {
8887  /* Search the subgroup that strands the table->size line.
8888  ** If the first group starts at 0 and goes past table->size
8889  ** upper will get -1, thus correctly signaling that no reordering
8890  ** should take place.
8891  */
8892  while (auxnode != NULL) {
8893  int thisLower = table->perm[auxnode->low];
8894  int thisUpper = thisLower + auxnode->size - 1;
8895  if (thisUpper >= table->size && thisLower < table->size)
8896  *upper = (unsigned int) thisLower - 1;
8897  auxnode = auxnode->younger;
8898  }
8899  }
8900  } else {
8901  /* Normal case: All the variables of the group exist. */
8902  *upper = (unsigned int) high;
8903  }
8904 
8905 #ifdef DD_DEBUG
8906  /* Make sure that all variables in group are contiguous. */
8907  assert(treenode->size >= *upper - *lower + 1);
8908 #endif
8909 
8910  return;
8911 
8912 } /* end of ddFindNodeHiLo */
8913 
8914 
8927 static int
8929  int * ptrX,
8930  int * ptrY)
8931 {
8932 #if 0
8933  if (entry[*ptrY] == entry[*ptrX]) {
8934  return((*ptrX) - (*ptrY));
8935  }
8936 #endif
8937  return(entry[*ptrY] - entry[*ptrX]);
8938 
8939 } /* end of ddUniqueCompareGroup */
8940 
8941 
8955 static int
8957  DdManager * table,
8958  int lower,
8959  int upper,
8960  DD_CHKFP checkFunction,
8961  int lazyFlag)
8962 {
8963  int *var;
8964  int i,j,x,xInit;
8965  int nvars;
8966  int classes;
8967  int result;
8968  int *sifted;
8969  int merged;
8970  int dissolve;
8971 #ifdef DD_STATS
8972  unsigned previousSize;
8973 #endif
8974  int xindex;
8975 
8976  nvars = table->size;
8977 
8978  /* Order variables to sift. */
8979  entry = NULL;
8980  sifted = NULL;
8981  var = ALLOC(int,nvars);
8982  if (var == NULL) {
8983  table->errorCode = CUDD_MEMORY_OUT;
8984  goto ddGroupSiftingOutOfMem;
8985  }
8986  entry = ALLOC(int,nvars);
8987  if (entry == NULL) {
8988  table->errorCode = CUDD_MEMORY_OUT;
8989  goto ddGroupSiftingOutOfMem;
8990  }
8991  sifted = ALLOC(int,nvars);
8992  if (sifted == NULL) {
8993  table->errorCode = CUDD_MEMORY_OUT;
8994  goto ddGroupSiftingOutOfMem;
8995  }
8996 
8997  /* Here we consider only one representative for each group. */
8998  for (i = 0, classes = 0; i < nvars; i++) {
8999  sifted[i] = 0;
9000  x = table->perm[i];
9001  if ((unsigned) x >= table->subtables[x].next) {
9002  entry[i] = table->subtables[x].keys;
9003  var[classes] = i;
9004  classes++;
9005  }
9006  }
9007 
9008  qsort((void *)var,classes,sizeof(int),
9010 
9011  if (lazyFlag) {
9012  for (i = 0; i < nvars; i ++) {
9013  ddResetVarHandled(table, i);
9014  }
9015  }
9016 
9017  /* Now sift. */
9018  for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
9019  if (ddTotalNumberSwapping >= table->siftMaxSwap)
9020  break;
9021  if (util_cpu_time() - table->startTime + table->reordTime
9022  > table->timeLimit) {
9023  table->autoDyn = 0; /* prevent further reordering */
9024  break;
9025  }
9026  xindex = var[i];
9027  if (sifted[xindex] == 1) /* variable already sifted as part of group */
9028  continue;
9029  x = table->perm[xindex]; /* find current level of this variable */
9030 
9031  if (x < lower || x > upper || table->subtables[x].bindVar == 1)
9032  continue;
9033 #ifdef DD_STATS
9034  previousSize = table->keys - table->isolated;
9035 #endif
9036 #ifdef DD_DEBUG
9037  /* x is bottom of group */
9038  assert((unsigned) x >= table->subtables[x].next);
9039 #endif
9040  if ((unsigned) x == table->subtables[x].next) {
9041  dissolve = 1;
9042  result = ddGroupSiftingAux(table,x,lower,upper,checkFunction,
9043  lazyFlag);
9044  } else {
9045  dissolve = 0;
9046  result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
9047  }
9048  if (!result) goto ddGroupSiftingOutOfMem;
9049 
9050  /* check for aggregation */
9051  merged = 0;
9052  if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) {
9053  x = table->perm[xindex]; /* find current level */
9054  if ((unsigned) x == table->subtables[x].next) { /* not part of a group */
9055  if (x != upper && sifted[table->invperm[x+1]] == 0 &&
9056  (unsigned) x+1 == table->subtables[x+1].next) {
9057  if (ddSecDiffCheck(table,x,x+1)) {
9058  merged =1;
9059  ddCreateGroup(table,x,x+1);
9060  }
9061  }
9062  if (x != lower && sifted[table->invperm[x-1]] == 0 &&
9063  (unsigned) x-1 == table->subtables[x-1].next) {
9064  if (ddSecDiffCheck(table,x-1,x)) {
9065  merged =1;
9066  ddCreateGroup(table,x-1,x);
9067  }
9068  }
9069  }
9070  }
9071 
9072  if (merged) { /* a group was created */
9073  /* move x to bottom of group */
9074  while ((unsigned) x < table->subtables[x].next)
9075  x = table->subtables[x].next;
9076  /* sift */
9077  result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
9078  if (!result) goto ddGroupSiftingOutOfMem;
9079 #ifdef DD_STATS
9080  if (table->keys < previousSize + table->isolated) {
9081  (void) fprintf(table->out,"_");
9082  } else if (table->keys > previousSize + table->isolated) {
9083  (void) fprintf(table->out,"^");
9084  } else {
9085  (void) fprintf(table->out,"*");
9086  }
9087  fflush(table->out);
9088  } else {
9089  if (table->keys < previousSize + table->isolated) {
9090  (void) fprintf(table->out,"-");
9091  } else if (table->keys > previousSize + table->isolated) {
9092  (void) fprintf(table->out,"+");
9093  } else {
9094  (void) fprintf(table->out,"=");
9095  }
9096  fflush(table->out);
9097 #endif
9098  }
9099 
9100  /* Mark variables in the group just sifted. */
9101  x = table->perm[xindex];
9102  if ((unsigned) x != table->subtables[x].next) {
9103  xInit = x;
9104  do {
9105  j = table->invperm[x];
9106  sifted[j] = 1;
9107  x = table->subtables[x].next;
9108  } while (x != xInit);
9109 
9110  /* Dissolve the group if it was created. */
9111  if (lazyFlag == 0 && dissolve) {
9112  do {
9113  j = table->subtables[x].next;
9114  table->subtables[x].next = x;
9115  x = j;
9116  } while (x != xInit);
9117  }
9118  }
9119 
9120 #ifdef DD_DEBUG
9121  if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:");
9122 #endif
9123 
9124  if (lazyFlag) ddSetVarHandled(table, xindex);
9125  } /* for */
9126 
9127  FREE(sifted);
9128  FREE(var);
9129  FREE(entry);
9130 
9131  return(1);
9132 
9133  ddGroupSiftingOutOfMem:
9134  if (entry != NULL) FREE(entry);
9135  if (var != NULL) FREE(var);
9136  if (sifted != NULL) FREE(sifted);
9137 
9138  return(0);
9139 
9140 } /* end of ddGroupSifting */
9141 
9142 
9155 static void
9157  DdManager * table,
9158  int x,
9159  int y)
9160 {
9161  int gybot;
9162 
9163 #ifdef DD_DEBUG
9164  assert(y == x+1);
9165 #endif
9166 
9167  /* Find bottom of second group. */
9168  gybot = y;
9169  while ((unsigned) gybot < table->subtables[gybot].next)
9170  gybot = table->subtables[gybot].next;
9171 
9172  /* Link groups. */
9173  table->subtables[x].next = y;
9174  table->subtables[gybot].next = x;
9175 
9176  return;
9177 
9178 } /* ddCreateGroup */
9179 
9180 
9196 static int
9198  DdManager * table,
9199  int x,
9200  int xLow,
9201  int xHigh,
9202  DD_CHKFP checkFunction,
9203  int lazyFlag)
9204 {
9205  Move *move;
9206  Move *moves; /* list of moves */
9207  int initialSize;
9208  int result;
9209  int y;
9210  int topbot;
9211 
9212 #ifdef DD_DEBUG
9213  if (pr > 0) (void) fprintf(table->out,
9214  "ddGroupSiftingAux from %d to %d\n",xLow,xHigh);
9215  assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */
9216 #endif
9217 
9218  initialSize = table->keys - table->isolated;
9219  moves = NULL;
9220 
9221  originalSize = initialSize; /* for lazy sifting */
9222 
9223  /* If we have a singleton, we check for aggregation in both
9224  ** directions before we sift.
9225  */
9226  if ((unsigned) x == table->subtables[x].next) {
9227  /* Will go down first, unless x == xHigh:
9228  ** Look for aggregation above x.
9229  */
9230  for (y = x; y > xLow; y--) {
9231  if (!checkFunction(table,y-1,y))
9232  break;
9233  topbot = table->subtables[y-1].next; /* find top of y-1's group */
9234  table->subtables[y-1].next = y;
9235  table->subtables[x].next = topbot; /* x is bottom of group so its */
9236  /* next is top of y-1's group */
9237  y = topbot + 1; /* add 1 for y--; new y is top of group */
9238  }
9239  /* Will go up first unless x == xlow:
9240  ** Look for aggregation below x.
9241  */
9242  for (y = x; y < xHigh; y++) {
9243  if (!checkFunction(table,y,y+1))
9244  break;
9245  /* find bottom of y+1's group */
9246  topbot = y + 1;
9247  while ((unsigned) topbot < table->subtables[topbot].next) {
9248  topbot = table->subtables[topbot].next;
9249  }
9250  table->subtables[topbot].next = table->subtables[y].next;
9251  table->subtables[y].next = y + 1;
9252  y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */
9253  }
9254  }
9255 
9256  /* Now x may be in the middle of a group.
9257  ** Find bottom of x's group.
9258  */
9259  while ((unsigned) x < table->subtables[x].next)
9260  x = table->subtables[x].next;
9261 
9262  if (x == xLow) { /* Sift down */
9263 #ifdef DD_DEBUG
9264  /* x must be a singleton */
9265  assert((unsigned) x == table->subtables[x].next);
9266 #endif
9267  if (x == xHigh) return(1); /* just one variable */
9268 
9269  if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
9270  goto ddGroupSiftingAuxOutOfMem;
9271  /* at this point x == xHigh, unless early term */
9272 
9273  /* move backward and stop at best position */
9274  result = ddGroupSiftingBackward(table,moves,initialSize,
9275  DD_SIFT_DOWN,lazyFlag);
9276 #ifdef DD_DEBUG
9277  assert(table->keys - table->isolated <= (unsigned) initialSize);
9278 #endif
9279  if (!result) goto ddGroupSiftingAuxOutOfMem;
9280 
9281  } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
9282 #ifdef DD_DEBUG
9283  /* x is bottom of group */
9284  assert((unsigned) x >= table->subtables[x].next);
9285 #endif
9286  /* Find top of x's group */
9287  x = table->subtables[x].next;
9288 
9289  if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
9290  goto ddGroupSiftingAuxOutOfMem;
9291  /* at this point x == xLow, unless early term */
9292 
9293  /* move backward and stop at best position */
9294  result = ddGroupSiftingBackward(table,moves,initialSize,
9295  DD_SIFT_UP,lazyFlag);
9296 #ifdef DD_DEBUG
9297  assert(table->keys - table->isolated <= (unsigned) initialSize);
9298 #endif
9299  if (!result) goto ddGroupSiftingAuxOutOfMem;
9300 
9301  } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
9302  if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
9303  goto ddGroupSiftingAuxOutOfMem;
9304  /* at this point x == xHigh, unless early term */
9305 
9306  /* Find top of group */
9307  if (moves) {
9308  x = moves->y;
9309  }
9310  while ((unsigned) x < table->subtables[x].next)
9311  x = table->subtables[x].next;
9312  x = table->subtables[x].next;
9313 #ifdef DD_DEBUG
9314  /* x should be the top of a group */
9315  assert((unsigned) x <= table->subtables[x].next);
9316 #endif
9317 
9318  if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
9319  goto ddGroupSiftingAuxOutOfMem;
9320 
9321  /* move backward and stop at best position */
9322  result = ddGroupSiftingBackward(table,moves,initialSize,
9323  DD_SIFT_UP,lazyFlag);
9324 #ifdef DD_DEBUG
9325  assert(table->keys - table->isolated <= (unsigned) initialSize);
9326 #endif
9327  if (!result) goto ddGroupSiftingAuxOutOfMem;
9328 
9329  } else { /* moving up first: shorter */
9330  /* Find top of x's group */
9331  x = table->subtables[x].next;
9332 
9333  if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
9334  goto ddGroupSiftingAuxOutOfMem;
9335  /* at this point x == xHigh, unless early term */
9336 
9337  if (moves) {
9338  x = moves->x;
9339  }
9340  while ((unsigned) x < table->subtables[x].next)
9341  x = table->subtables[x].next;
9342 #ifdef DD_DEBUG
9343  /* x is bottom of a group */
9344  assert((unsigned) x >= table->subtables[x].next);
9345 #endif
9346 
9347  if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
9348  goto ddGroupSiftingAuxOutOfMem;
9349 
9350  /* move backward and stop at best position */
9351  result = ddGroupSiftingBackward(table,moves,initialSize,
9352  DD_SIFT_DOWN,lazyFlag);
9353 #ifdef DD_DEBUG
9354  assert(table->keys - table->isolated <= (unsigned) initialSize);
9355 #endif
9356  if (!result) goto ddGroupSiftingAuxOutOfMem;
9357  }
9358 
9359  while (moves != NULL) {
9360  move = moves->next;
9361  cuddDeallocMove(table, moves);
9362  moves = move;
9363  }
9364 
9365  return(1);
9366 
9367  ddGroupSiftingAuxOutOfMem:
9368  while (moves != NULL) {
9369  move = moves->next;
9370  cuddDeallocMove(table, moves);
9371  moves = move;
9372  }
9373 
9374  return(0);
9375 
9376 } /* end of ddGroupSiftingAux */
9377 
9378 
9394 static int
9396  DdManager * table,
9397  int y,
9398  int xLow,
9399  DD_CHKFP checkFunction,
9400  Move ** moves)
9401 {
9402  Move *move;
9403  int x;
9404  int size;
9405  int i;
9406  int gxtop,gybot;
9407  int limitSize;
9408  int xindex, yindex;
9409  int zindex;
9410  int z;
9411  int isolated;
9412  int L; /* lower bound on DD size */
9413 #ifdef DD_DEBUG
9414  int checkL;
9415 #endif
9416 
9417  yindex = table->invperm[y];
9418 
9419  /* Initialize the lower bound.
9420  ** The part of the DD below the bottom of y's group will not change.
9421  ** The part of the DD above y that does not interact with any
9422  ** variable of y's group will not change.
9423  ** The rest may vanish in the best case, except for
9424  ** the nodes at level xLow, which will not vanish, regardless.
9425  ** What we use here is not really a lower bound, because we ignore
9426  ** the interactions with all variables except y.
9427  */
9428  limitSize = L = table->keys - table->isolated;
9429  gybot = y;
9430  while ((unsigned) gybot < table->subtables[gybot].next)
9431  gybot = table->subtables[gybot].next;
9432  for (z = xLow + 1; z <= gybot; z++) {
9433  zindex = table->invperm[z];
9434  if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
9435  isolated = table->vars[zindex]->ref == 1;
9436  L -= table->subtables[z].keys - isolated;
9437  }
9438  }
9439 
9440  x = cuddNextLow(table,y);
9441  while (x >= xLow && L <= limitSize) {
9442 #ifdef DD_DEBUG
9443  gybot = y;
9444  while ((unsigned) gybot < table->subtables[gybot].next)
9445  gybot = table->subtables[gybot].next;
9446  checkL = table->keys - table->isolated;
9447  for (z = xLow + 1; z <= gybot; z++) {
9448  zindex = table->invperm[z];
9449  if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
9450  isolated = table->vars[zindex]->ref == 1;
9451  checkL -= table->subtables[z].keys - isolated;
9452  }
9453  }
9454  if (pr > 0 && L != checkL) {
9455  (void) fprintf(table->out,
9456  "Inaccurate lower bound: L = %d checkL = %d\n",
9457  L, checkL);
9458  }
9459 #endif
9460  gxtop = table->subtables[x].next;
9461  if (checkFunction(table,x,y)) {
9462  /* Group found, attach groups */
9463  table->subtables[x].next = y;
9464  i = table->subtables[y].next;
9465  while (table->subtables[i].next != (unsigned) y)
9466  i = table->subtables[i].next;
9467  table->subtables[i].next = gxtop;
9468  move = (Move *)cuddDynamicAllocNode(table);
9469  if (move == NULL) goto ddGroupSiftingUpOutOfMem;
9470  move->x = x;
9471  move->y = y;
9472  move->flags = MTR_NEWNODE;
9473  move->size = table->keys - table->isolated;
9474  move->next = *moves;
9475  *moves = move;
9476  } else if (table->subtables[x].next == (unsigned) x &&
9477  table->subtables[y].next == (unsigned) y) {
9478  /* x and y are self groups */
9479  xindex = table->invperm[x];
9480  size = cuddSwapInPlace(table,x,y);
9481 #ifdef DD_DEBUG
9482  assert(table->subtables[x].next == (unsigned) x);
9483  assert(table->subtables[y].next == (unsigned) y);
9484 #endif
9485  if (size == 0) goto ddGroupSiftingUpOutOfMem;
9486  /* Update the lower bound. */
9487  if (cuddTestInteract(table,xindex,yindex)) {
9488  isolated = table->vars[xindex]->ref == 1;
9489  L += table->subtables[y].keys - isolated;
9490  }
9491  move = (Move *)cuddDynamicAllocNode(table);
9492  if (move == NULL) goto ddGroupSiftingUpOutOfMem;
9493  move->x = x;
9494  move->y = y;
9495  move->flags = MTR_DEFAULT;
9496  move->size = size;
9497  move->next = *moves;
9498  *moves = move;
9499 
9500 #ifdef DD_DEBUG
9501  if (pr > 0) (void) fprintf(table->out,
9502  "ddGroupSiftingUp (2 single groups):\n");
9503 #endif
9504  if ((double) size > (double) limitSize * table->maxGrowth)
9505  return(1);
9506  if (size < limitSize) limitSize = size;
9507  } else { /* Group move */
9508  size = ddGroupMove(table,x,y,moves);
9509  if (size == 0) goto ddGroupSiftingUpOutOfMem;
9510  /* Update the lower bound. */
9511  z = (*moves)->y;
9512  do {
9513  zindex = table->invperm[z];
9514  if (cuddTestInteract(table,zindex,yindex)) {
9515  isolated = table->vars[zindex]->ref == 1;
9516  L += table->subtables[z].keys - isolated;
9517  }
9518  z = table->subtables[z].next;
9519  } while (z != (int) (*moves)->y);
9520  if ((double) size > (double) limitSize * table->maxGrowth)
9521  return(1);
9522  if (size < limitSize) limitSize = size;
9523  }
9524  y = gxtop;
9525  x = cuddNextLow(table,y);
9526  }
9527 
9528  return(1);
9529 
9530  ddGroupSiftingUpOutOfMem:
9531  while (*moves != NULL) {
9532  move = (*moves)->next;
9533  cuddDeallocMove(table, *moves);
9534  *moves = move;
9535  }
9536  return(0);
9537 
9538 } /* end of ddGroupSiftingUp */
9539 
9540 
9552 static int
9554  DdManager * table,
9555  int x,
9556  int xHigh,
9557  DD_CHKFP checkFunction,
9558  Move ** moves)
9559 {
9560  Move *move;
9561  int y;
9562  int size;
9563  int limitSize;
9564  int gxtop,gybot;
9565  int R; /* upper bound on node decrease */
9566  int xindex, yindex;
9567  int isolated, allVars;
9568  int z;
9569  int zindex;
9570 #ifdef DD_DEBUG
9571  int checkR;
9572 #endif
9573 
9574  /* If the group consists of simple variables, there is no point in
9575  ** sifting it down. This check is redundant if the projection functions
9576  ** do not have external references, because the computation of the
9577  ** lower bound takes care of the problem. It is necessary otherwise to
9578  ** prevent the sifting down of simple variables. */
9579  y = x;
9580  allVars = 1;
9581  do {
9582  if (table->subtables[y].keys != 1) {
9583  allVars = 0;
9584  break;
9585  }
9586  y = table->subtables[y].next;
9587  } while (table->subtables[y].next != (unsigned) x);
9588  if (allVars)
9589  return(1);
9590 
9591  /* Initialize R. */
9592  xindex = table->invperm[x];
9593  gxtop = table->subtables[x].next;
9594  limitSize = size = table->keys - table->isolated;
9595  R = 0;
9596  for (z = xHigh; z > gxtop; z--) {
9597  zindex = table->invperm[z];
9598  if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
9599  isolated = table->vars[zindex]->ref == 1;
9600  R += table->subtables[z].keys - isolated;
9601  }
9602  }
9603 
9604  y = cuddNextHigh(table,x);
9605  while (y <= xHigh && size - R < limitSize) {
9606 #ifdef DD_DEBUG
9607  gxtop = table->subtables[x].next;
9608  checkR = 0;
9609  for (z = xHigh; z > gxtop; z--) {
9610  zindex = table->invperm[z];
9611  if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
9612  isolated = table->vars[zindex]->ref == 1;
9613  checkR += table->subtables[z].keys - isolated;
9614  }
9615  }
9616  assert(R >= checkR);
9617 #endif
9618  /* Find bottom of y group. */
9619  gybot = table->subtables[y].next;
9620  while (table->subtables[gybot].next != (unsigned) y)
9621  gybot = table->subtables[gybot].next;
9622 
9623  if (checkFunction(table,x,y)) {
9624  /* Group found: attach groups and record move. */
9625  gxtop = table->subtables[x].next;
9626  table->subtables[x].next = y;
9627  table->subtables[gybot].next = gxtop;
9628  move = (Move *)cuddDynamicAllocNode(table);
9629  if (move == NULL) goto ddGroupSiftingDownOutOfMem;
9630  move->x = x;
9631  move->y = y;
9632  move->flags = MTR_NEWNODE;
9633  move->size = table->keys - table->isolated;
9634  move->next = *moves;
9635  *moves = move;
9636  } else if (table->subtables[x].next == (unsigned) x &&
9637  table->subtables[y].next == (unsigned) y) {
9638  /* x and y are self groups */
9639  /* Update upper bound on node decrease. */
9640  yindex = table->invperm[y];
9641  if (cuddTestInteract(table,xindex,yindex)) {
9642  isolated = table->vars[yindex]->ref == 1;
9643  R -= table->subtables[y].keys - isolated;
9644  }
9645  size = cuddSwapInPlace(table,x,y);
9646 #ifdef DD_DEBUG
9647  assert(table->subtables[x].next == (unsigned) x);
9648  assert(table->subtables[y].next == (unsigned) y);
9649 #endif
9650  if (size == 0) goto ddGroupSiftingDownOutOfMem;
9651 
9652  /* Record move. */
9653  move = (Move *) cuddDynamicAllocNode(table);
9654  if (move == NULL) goto ddGroupSiftingDownOutOfMem;
9655  move->x = x;
9656  move->y = y;
9657  move->flags = MTR_DEFAULT;
9658  move->size = size;
9659  move->next = *moves;
9660  *moves = move;
9661 
9662 #ifdef DD_DEBUG
9663  if (pr > 0) (void) fprintf(table->out,
9664  "ddGroupSiftingDown (2 single groups):\n");
9665 #endif
9666  if ((double) size > (double) limitSize * table->maxGrowth)
9667  return(1);
9668  if (size < limitSize) limitSize = size;
9669 
9670  x = y;
9671  y = cuddNextHigh(table,x);
9672  } else { /* Group move */
9673  /* Update upper bound on node decrease: first phase. */
9674  gxtop = table->subtables[x].next;
9675  z = gxtop + 1;
9676  do {
9677  zindex = table->invperm[z];
9678  if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
9679  isolated = table->vars[zindex]->ref == 1;
9680  R -= table->subtables[z].keys - isolated;
9681  }
9682  z++;
9683  } while (z <= gybot);
9684  size = ddGroupMove(table,x,y,moves);
9685  if (size == 0) goto ddGroupSiftingDownOutOfMem;
9686  if ((double) size > (double) limitSize * table->maxGrowth)
9687  return(1);
9688  if (size < limitSize) limitSize = size;
9689 
9690  /* Update upper bound on node decrease: second phase. */
9691  gxtop = table->subtables[gybot].next;
9692  for (z = gxtop + 1; z <= gybot; z++) {
9693  zindex = table->invperm[z];
9694  if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
9695  isolated = table->vars[zindex]->ref == 1;
9696  R += table->subtables[z].keys - isolated;
9697  }
9698  }
9699  }
9700  x = gybot;
9701  y = cuddNextHigh(table,x);
9702  }
9703 
9704  return(1);
9705 
9706  ddGroupSiftingDownOutOfMem:
9707  while (*moves != NULL) {
9708  move = (*moves)->next;
9709  cuddDeallocMove(table, *moves);
9710  *moves = move;
9711  }
9712 
9713  return(0);
9714 
9715 } /* end of ddGroupSiftingDown */
9716 
9717 
9728 static int
9730  DdManager * table,
9731  int x,
9732  int y,
9733  Move ** moves)
9734 {
9735  Move *move;
9736  int size;
9737  int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
9738  int swapx,swapy;
9739 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
9740  int initialSize,bestSize;
9741 #endif
9742 
9743 #ifdef DD_DEBUG
9744  /* We assume that x < y */
9745  assert(x < y);
9746 #endif
9747  /* Find top, bottom, and size for the two groups. */
9748  xbot = x;
9749  xtop = table->subtables[x].next;
9750  xsize = xbot - xtop + 1;
9751  ybot = y;
9752  while ((unsigned) ybot < table->subtables[ybot].next)
9753  ybot = table->subtables[ybot].next;
9754  ytop = y;
9755  ysize = ybot - ytop + 1;
9756 
9757 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
9758  initialSize = bestSize = table->keys - table->isolated;
9759 #endif
9760  /* Sift the variables of the second group up through the first group */
9761  for (i = 1; i <= ysize; i++) {
9762  for (j = 1; j <= xsize; j++) {
9763  size = cuddSwapInPlace(table,x,y);
9764  if (size == 0) goto ddGroupMoveOutOfMem;
9765 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
9766  if (size < bestSize)
9767  bestSize = size;
9768 #endif
9769  swapx = x; swapy = y;
9770  y = x;
9771  x = cuddNextLow(table,y);
9772  }
9773  y = ytop + i;
9774  x = cuddNextLow(table,y);
9775  }
9776 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
9777  if ((bestSize < initialSize) && (bestSize < size))
9778  (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size);
9779 #endif
9780 
9781  /* fix groups */
9782  y = xtop; /* ytop is now where xtop used to be */
9783  for (i = 0; i < ysize - 1; i++) {
9784  table->subtables[y].next = cuddNextHigh(table,y);
9785  y = cuddNextHigh(table,y);
9786  }
9787  table->subtables[y].next = xtop; /* y is bottom of its group, join */
9788  /* it to top of its group */
9789  x = cuddNextHigh(table,y);
9790  newxtop = x;
9791  for (i = 0; i < xsize - 1; i++) {
9792  table->subtables[x].next = cuddNextHigh(table,x);
9793  x = cuddNextHigh(table,x);
9794  }
9795  table->subtables[x].next = newxtop; /* x is bottom of its group, join */
9796  /* it to top of its group */
9797 #ifdef DD_DEBUG
9798  if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n");
9799 #endif
9800 
9801  /* Store group move */
9802  move = (Move *) cuddDynamicAllocNode(table);
9803  if (move == NULL) goto ddGroupMoveOutOfMem;
9804  move->x = swapx;
9805  move->y = swapy;
9806  move->flags = MTR_DEFAULT;
9807  move->size = table->keys - table->isolated;
9808  move->next = *moves;
9809  *moves = move;
9810 
9811  return(table->keys - table->isolated);
9812 
9813  ddGroupMoveOutOfMem:
9814  while (*moves != NULL) {
9815  move = (*moves)->next;
9816  cuddDeallocMove(table, *moves);
9817  *moves = move;
9818  }
9819  return(0);
9820 
9821 } /* end of ddGroupMove */
9822 
9823 
9834 static int
9836  DdManager * table,
9837  int x,
9838  int y)
9839 {
9840  int size;
9841  int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
9842 
9843 
9844 #ifdef DD_DEBUG
9845  /* We assume that x < y */
9846  assert(x < y);
9847 #endif
9848 
9849  /* Find top, bottom, and size for the two groups. */
9850  xbot = x;
9851  xtop = table->subtables[x].next;
9852  xsize = xbot - xtop + 1;
9853  ybot = y;
9854  while ((unsigned) ybot < table->subtables[ybot].next)
9855  ybot = table->subtables[ybot].next;
9856  ytop = y;
9857  ysize = ybot - ytop + 1;
9858 
9859  /* Sift the variables of the second group up through the first group */
9860  for (i = 1; i <= ysize; i++) {
9861  for (j = 1; j <= xsize; j++) {
9862  size = cuddSwapInPlace(table,x,y);
9863  if (size == 0)
9864  return(0);
9865  y = x;
9866  x = cuddNextLow(table,y);
9867  }
9868  y = ytop + i;
9869  x = cuddNextLow(table,y);
9870  }
9871 
9872  /* fix groups */
9873  y = xtop;
9874  for (i = 0; i < ysize - 1; i++) {
9875  table->subtables[y].next = cuddNextHigh(table,y);
9876  y = cuddNextHigh(table,y);
9877  }
9878  table->subtables[y].next = xtop; /* y is bottom of its group, join */
9879  /* to its top */
9880  x = cuddNextHigh(table,y);
9881  newxtop = x;
9882  for (i = 0; i < xsize - 1; i++) {
9883  table->subtables[x].next = cuddNextHigh(table,x);
9884  x = cuddNextHigh(table,x);
9885  }
9886  table->subtables[x].next = newxtop; /* x is bottom of its group, join */
9887  /* to its top */
9888 #ifdef DD_DEBUG
9889  if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n");
9890 #endif
9891 
9892  return(1);
9893 
9894 } /* end of ddGroupMoveBackward */
9895 
9896 
9908 static int
9910  DdManager * table,
9911  Move * moves,
9912  int size,
9913  int upFlag,
9914  int lazyFlag)
9915 {
9916  Move *move;
9917  int res;
9918  Move *end_move;
9919  int diff, tmp_diff;
9920  int index;
9921  unsigned int pairlev;
9922 
9923  if (lazyFlag) {
9924  end_move = NULL;
9925 
9926  /* Find the minimum size, and the earliest position at which it
9927  ** was achieved. */
9928  for (move = moves; move != NULL; move = move->next) {
9929  if (move->size < size) {
9930  size = move->size;
9931  end_move = move;
9932  } else if (move->size == size) {
9933  if (end_move == NULL) end_move = move;
9934  }
9935  }
9936 
9937  /* Find among the moves that give minimum size the one that
9938  ** minimizes the distance from the corresponding variable. */
9939  if (moves != NULL) {
9940  diff = Cudd_ReadSize(table) + 1;
9941  index = (upFlag == 1) ?
9942  table->invperm[moves->x] : table->invperm[moves->y];
9943  pairlev =
9944  (unsigned) table->perm[Cudd_bddReadPairIndex(table, index)];
9945 
9946  for (move = moves; move != NULL; move = move->next) {
9947  if (move->size == size) {
9948  if (upFlag == 1) {
9949  tmp_diff = (move->x > pairlev) ?
9950  move->x - pairlev : pairlev - move->x;
9951  } else {
9952  tmp_diff = (move->y > pairlev) ?
9953  move->y - pairlev : pairlev - move->y;
9954  }
9955  if (tmp_diff < diff) {
9956  diff = tmp_diff;
9957  end_move = move;
9958  }
9959  }
9960  }
9961  }
9962  } else {
9963  /* Find the minimum size. */
9964  for (move = moves; move != NULL; move = move->next) {
9965  if (move->size < size) {
9966  size = move->size;
9967  }
9968  }
9969  }
9970 
9971  /* In case of lazy sifting, end_move identifies the position at
9972  ** which we want to stop. Otherwise, we stop as soon as we meet
9973  ** the minimum size. */
9974  for (move = moves; move != NULL; move = move->next) {
9975  if (lazyFlag) {
9976  if (move == end_move) return(1);
9977  } else {
9978  if (move->size == size) return(1);
9979  }
9980  if ((table->subtables[move->x].next == move->x) &&
9981  (table->subtables[move->y].next == move->y)) {
9982  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
9983  if (!res) return(0);
9984 #ifdef DD_DEBUG
9985  if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n");
9986  assert(table->subtables[move->x].next == move->x);
9987  assert(table->subtables[move->y].next == move->y);
9988 #endif
9989  } else { /* Group move necessary */
9990  if (move->flags == MTR_NEWNODE) {
9991  ddDissolveGroup(table,(int)move->x,(int)move->y);
9992  } else {
9993  res = ddGroupMoveBackward(table,(int)move->x,(int)move->y);
9994  if (!res) return(0);
9995  }
9996  }
9997 
9998  }
9999 
10000  return(1);
10001 
10002 } /* end of ddGroupSiftingBackward */
10003 
10004 
10015 static void
10017  DdManager * table,
10018  MtrNode * treenode,
10019  int low,
10020  int high)
10021 {
10022  int i;
10023  MtrNode *auxnode;
10024  int saveindex;
10025  int newindex;
10026 
10027  /* Merge all variables from low to high in one group, unless
10028  ** this is the topmost group. In such a case we do not merge lest
10029  ** we lose the symmetry information. */
10030  if (treenode != table->tree) {
10031  for (i = low; i < high; i++)
10032  table->subtables[i].next = i+1;
10033  table->subtables[high].next = low;
10034  }
10035 
10036  /* Adjust the index fields of the tree nodes. If a node is the
10037  ** first child of its parent, then the parent may also need adjustment. */
10038  saveindex = treenode->index;
10039  newindex = table->invperm[low];
10040  auxnode = treenode;
10041  do {
10042  auxnode->index = newindex;
10043  if (auxnode->parent == NULL ||
10044  (int) auxnode->parent->index != saveindex)
10045  break;
10046  auxnode = auxnode->parent;
10047  } while (1);
10048  return;
10049 
10050 } /* end of ddMergeGroups */
10051 
10052 
10063 static void
10065  DdManager * table,
10066  int x,
10067  int y)
10068 {
10069  int topx;
10070  int boty;
10071 
10072  /* find top and bottom of the two groups */
10073  boty = y;
10074  while ((unsigned) boty < table->subtables[boty].next)
10075  boty = table->subtables[boty].next;
10076 
10077  topx = table->subtables[boty].next;
10078 
10079  table->subtables[boty].next = y;
10080  table->subtables[x].next = topx;
10081 
10082  return;
10083 
10084 } /* end of ddDissolveGroup */
10085 
10086 
10097 static int
10099  DdManager * table,
10100  int x,
10101  int y)
10102 {
10103  return(0);
10104 
10105 } /* end of ddNoCheck */
10106 
10107 
10121 static int
10123  DdManager * table,
10124  int x,
10125  int y)
10126 {
10127  double Nx,Nx_1;
10128  double Sx;
10129  double threshold;
10130  int xindex,yindex;
10131 
10132  if (x==0) return(0);
10133 
10134 #ifdef DD_STATS
10135  secdiffcalls++;
10136 #endif
10137  Nx = (double) table->subtables[x].keys;
10138  Nx_1 = (double) table->subtables[x-1].keys;
10139  Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1);
10140 
10141  threshold = table->recomb / 100.0;
10142  if (Sx < threshold) {
10143  xindex = table->invperm[x];
10144  yindex = table->invperm[y];
10145  if (cuddTestInteract(table,xindex,yindex)) {
10146 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
10147  (void) fprintf(table->out,
10148  "Second difference for %d = %g Pos(%d)\n",
10149  table->invperm[x],Sx,x);
10150 #endif
10151 #ifdef DD_STATS
10152  secdiff++;
10153 #endif
10154  return(1);
10155  } else {
10156 #ifdef DD_STATS
10157  secdiffmisfire++;
10158 #endif
10159  return(0);
10160  }
10161 
10162  }
10163  return(0);
10164 
10165 } /* end of ddSecDiffCheck */
10166 
10167 
10178 static int
10180  DdManager * table,
10181  int x,
10182  int y)
10183 {
10184  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
10185  DdNode *one;
10186  unsigned comple; /* f0 is complemented */
10187  int notproj; /* f is not a projection function */
10188  int arccount; /* number of arcs from layer x to layer y */
10189  int TotalRefCount; /* total reference count of layer y minus 1 */
10190  int counter; /* number of nodes of layer x that are allowed */
10191  /* to violate extended symmetry conditions */
10192  int arccounter; /* number of arcs into layer y that are allowed */
10193  /* to come from layers other than x */
10194  int i;
10195  int xindex;
10196  int yindex;
10197  int res;
10198  int slots;
10199  DdNodePtr *list;
10200  DdNode *sentinel = &(table->sentinel);
10201 
10202  xindex = table->invperm[x];
10203  yindex = table->invperm[y];
10204 
10205  /* If the two variables do not interact, we do not want to merge them. */
10206  if (!cuddTestInteract(table,xindex,yindex))
10207  return(0);
10208 
10209 #ifdef DD_DEBUG
10210  /* Checks that x and y do not contain just the projection functions.
10211  ** With the test on interaction, these test become redundant,
10212  ** because an isolated projection function does not interact with
10213  ** any other variable.
10214  */
10215  if (table->subtables[x].keys == 1) {
10216  assert(table->vars[xindex]->ref != 1);
10217  }
10218  if (table->subtables[y].keys == 1) {
10219  assert(table->vars[yindex]->ref != 1);
10220  }
10221 #endif
10222 
10223 #ifdef DD_STATS
10224  extsymmcalls++;
10225 #endif
10226 
10227  arccount = 0;
10228  counter = (int) (table->subtables[x].keys *
10229  (table->symmviolation/100.0) + 0.5);
10230  one = DD_ONE(table);
10231 
10232  slots = table->subtables[x].slots;
10233  list = table->subtables[x].nodelist;
10234  for (i = 0; i < slots; i++) {
10235  f = list[i];
10236  while (f != sentinel) {
10237  /* Find f1, f0, f11, f10, f01, f00. */
10238  f1 = cuddT(f);
10239  f0 = Cudd_Regular(cuddE(f));
10240  comple = Cudd_IsComplement(cuddE(f));
10241  notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1;
10242  if (f1->index == (unsigned) yindex) {
10243  arccount++;
10244  f11 = cuddT(f1); f10 = cuddE(f1);
10245  } else {
10246  if ((int) f0->index != yindex) {
10247  /* If f is an isolated projection function it is
10248  ** allowed to bypass layer y.
10249  */
10250  if (notproj) {
10251  if (counter == 0)
10252  return(0);
10253  counter--; /* f bypasses layer y */
10254  }
10255  }
10256  f11 = f10 = f1;
10257  }
10258  if ((int) f0->index == yindex) {
10259  arccount++;
10260  f01 = cuddT(f0); f00 = cuddE(f0);
10261  } else {
10262  f01 = f00 = f0;
10263  }
10264  if (comple) {
10265  f01 = Cudd_Not(f01);
10266  f00 = Cudd_Not(f00);
10267  }
10268 
10269  /* Unless we are looking at a projection function
10270  ** without external references except the one from the
10271  ** table, we insist that f01 == f10 or f11 == f00
10272  */
10273  if (notproj) {
10274  if (f01 != f10 && f11 != f00) {
10275  if (counter == 0)
10276  return(0);
10277  counter--;
10278  }
10279  }
10280 
10281  f = f->next;
10282  } /* while */
10283  } /* for */
10284 
10285  /* Calculate the total reference counts of y */
10286  TotalRefCount = -1; /* -1 for projection function */
10287  slots = table->subtables[y].slots;
10288  list = table->subtables[y].nodelist;
10289  for (i = 0; i < slots; i++) {
10290  f = list[i];
10291  while (f != sentinel) {
10292  TotalRefCount += f->ref;
10293  f = f->next;
10294  }
10295  }
10296 
10297  arccounter = (int) (table->subtables[y].keys *
10298  (table->arcviolation/100.0) + 0.5);
10299  res = arccount >= TotalRefCount - arccounter;
10300 
10301 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
10302  if (res) {
10303  (void) fprintf(table->out,
10304  "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n",
10305  xindex,yindex,x,y);
10306  }
10307 #endif
10308 
10309 #ifdef DD_STATS
10310  if (res)
10311  extsymm++;
10312 #endif
10313  return(res);
10314 
10315 } /* end ddExtSymmCheck */
10316 
10317 
10328 static int
10330  DdManager * table,
10331  int x,
10332  int y)
10333 {
10334  int xindex = table->invperm[x];
10335  int yindex = table->invperm[y];
10336 
10337  if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0);
10338 
10339  if (Cudd_bddReadPairIndex(table, xindex) == yindex) {
10340  if (ddIsVarHandled(table, xindex) ||
10341  ddIsVarHandled(table, yindex)) {
10342  if (Cudd_bddIsVarToBeGrouped(table, xindex) ||
10343  Cudd_bddIsVarToBeGrouped(table, yindex) ) {
10344  if (table->keys - table->isolated <= originalSize) {
10345  return(1);
10346  }
10347  }
10348  }
10349  }
10350 
10351  return(0);
10352 
10353 } /* end of ddVarGroupCheck */
10354 
10355 
10368 static int
10370  DdManager *dd,
10371  int index)
10372 {
10373  if (index >= dd->size || index < 0) return(0);
10374  dd->subtables[dd->perm[index]].varHandled = 1;
10375  return(1);
10376 
10377 } /* end of ddSetVarHandled */
10378 
10379 
10392 static int
10394  DdManager *dd,
10395  int index)
10396 {
10397  if (index >= dd->size || index < 0) return(0);
10398  dd->subtables[dd->perm[index]].varHandled = 0;
10399  return(1);
10400 
10401 } /* end of ddResetVarHandled */
10402 
10403 
10416 static int
10418  DdManager *dd,
10419  int index)
10420 {
10421  if (index >= dd->size || index < 0) return(-1);
10422  return dd->subtables[dd->perm[index]].varHandled;
10423 
10424 } /* end of ddIsVarHandled */
10425 
10485 /*---------------------------------------------------------------------------*/
10486 /* Constant declarations */
10487 /*---------------------------------------------------------------------------*/
10488 
10489 
10490 /*---------------------------------------------------------------------------*/
10491 /* Stucture declarations */
10492 /*---------------------------------------------------------------------------*/
10493 
10494 
10495 /*---------------------------------------------------------------------------*/
10496 /* Type declarations */
10497 /*---------------------------------------------------------------------------*/
10498 
10499 
10500 /*---------------------------------------------------------------------------*/
10501 /* Variable declarations */
10502 /*---------------------------------------------------------------------------*/
10503 
10504 //#ifndef lint
10505 //static char rcsid[] DD_UNUSED = "$Id: cuddInit.c,v 1.34 2012/02/05 01:07:19 fabio Exp $";
10506 //#endif
10507 
10508 /*---------------------------------------------------------------------------*/
10509 /* Macro declarations */
10510 /*---------------------------------------------------------------------------*/
10511 
10512 
10515 /*---------------------------------------------------------------------------*/
10516 /* Static function prototypes */
10517 /*---------------------------------------------------------------------------*/
10518 
10519 
10523 /*---------------------------------------------------------------------------*/
10524 /* Definition of exported functions */
10525 /*---------------------------------------------------------------------------*/
10526 
10543 DdManager *
10545  unsigned int numVars /* initial number of BDD variables (i.e., subtables) */,
10546  unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */,
10547  unsigned int numSlots /* initial size of the unique tables */,
10548  unsigned int cacheSize /* initial size of the cache */,
10549  unsigned long maxMemory /* target maximum memory occupation */)
10550 {
10551  DdManager *unique;
10552  int i,result;
10553  DdNode *one, *zero;
10554  unsigned int maxCacheSize;
10555  unsigned int looseUpTo;
10556  extern DD_OOMFP MMoutOfMemory;
10557  DD_OOMFP saveHandler;
10558 
10559  if (maxMemory == 0) {
10560  maxMemory = getSoftDataLimit();
10561  }
10562  looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) /
10564  unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo);
10565  if (unique == NULL) return(NULL);
10566  unique->maxmem = (unsigned long) maxMemory / 10 * 9;
10567  maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) /
10569  result = cuddInitCache(unique,cacheSize,maxCacheSize);
10570  if (result == 0) return(NULL);
10571 
10572  saveHandler = MMoutOfMemory;
10573  MMoutOfMemory = Cudd_OutOfMem;
10574  unique->stash = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4);
10575  MMoutOfMemory = saveHandler;
10576  if (unique->stash == NULL) {
10577  (void) fprintf(unique->err,"Unable to set aside memory\n");
10578  }
10579 
10580  /* Initialize constants. */
10581  unique->one = cuddUniqueConst(unique,1.0);
10582  if (unique->one == NULL) return(0);
10583  cuddRef(unique->one);
10584  unique->zero = cuddUniqueConst(unique,0.0);
10585  if (unique->zero == NULL) return(0);
10586  cuddRef(unique->zero);
10587 #ifdef HAVE_IEEE_754
10588  if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 ||
10590  (void) fprintf(unique->err,"Warning: Crippled infinite values\n");
10591  (void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n");
10592  }
10593 #endif
10594  unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL);
10595  if (unique->plusinfinity == NULL) return(0);
10596  cuddRef(unique->plusinfinity);
10598  if (unique->minusinfinity == NULL) return(0);
10599  cuddRef(unique->minusinfinity);
10600  unique->background = unique->zero;
10601 
10602  /* The logical zero is different from the CUDD_VALUE_TYPE zero! */
10603  one = unique->one;
10604  zero = Cudd_Not(one);
10605  /* Create the projection functions. */
10606  unique->vars = ALLOC(DdNodePtr,unique->maxSize);
10607  if (unique->vars == NULL) {
10608  unique->errorCode = CUDD_MEMORY_OUT;
10609  return(NULL);
10610  }
10611  for (i = 0; i < unique->size; i++) {
10612  unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
10613  if (unique->vars[i] == NULL) return(0);
10614  cuddRef(unique->vars[i]);
10615  }
10616 
10617  if (unique->sizeZ)
10618  cuddZddInitUniv(unique);
10619 
10620  unique->memused += sizeof(DdNode *) * unique->maxSize;
10621 
10622  return(unique);
10623 
10624 } /* end of Cudd_Init */
10625 
10626 
10640 void
10642  DdManager * unique)
10643 {
10644  if (unique->stash != NULL) FREE(unique->stash);
10645  cuddFreeTable(unique);
10646 
10647 } /* end of Cudd_Quit */
10648 
10649 
10650 /*---------------------------------------------------------------------------*/
10651 /* Definition of internal functions */
10652 /*---------------------------------------------------------------------------*/
10653 
10654 
10667 int
10669  DdManager * zdd)
10670 {
10671  DdNode *p, *res;
10672  int i;
10673 
10674  zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ);
10675  if (zdd->univ == NULL) {
10676  zdd->errorCode = CUDD_MEMORY_OUT;
10677  return(0);
10678  }
10679 
10680  res = DD_ONE(zdd);
10681  cuddRef(res);
10682  for (i = zdd->sizeZ - 1; i >= 0; i--) {
10683  unsigned int index = zdd->invpermZ[i];
10684  p = res;
10685  res = cuddUniqueInterZdd(zdd, index, p, p);
10686  if (res == NULL) {
10687  Cudd_RecursiveDerefZdd(zdd,p);
10688  FREE(zdd->univ);
10689  return(0);
10690  }
10691  cuddRef(res);
10692  cuddDeref(p);
10693  zdd->univ[i] = res;
10694  }
10695 
10696 #ifdef DD_VERBOSE
10697  cuddZddP(zdd, zdd->univ[0]);
10698 #endif
10699 
10700  return(1);
10701 
10702 } /* end of cuddZddInitUniv */
10703 
10704 
10716 void
10718  DdManager * zdd)
10719 {
10720  if (zdd->univ) {
10721  Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]);
10722  FREE(zdd->univ);
10723  }
10724 
10725 } /* end of cuddZddFreeUniv */
10726 
10727 
10728 /*---------------------------------------------------------------------------*/
10729 /* Definition of static functions */
10730 /*---------------------------------------------------------------------------*/
10731 
10810 /*---------------------------------------------------------------------------*/
10811 /* Constant declarations */
10812 /*---------------------------------------------------------------------------*/
10813 
10814 #if SIZEOF_LONG == 8
10815 #define BPL 64
10816 #define LOGBPL 6
10817 #else
10818 #define BPL 32
10819 #define LOGBPL 5
10820 #endif
10821 
10822 /*---------------------------------------------------------------------------*/
10823 /* Stucture declarations */
10824 /*---------------------------------------------------------------------------*/
10825 
10826 
10827 /*---------------------------------------------------------------------------*/
10828 /* Type declarations */
10829 /*---------------------------------------------------------------------------*/
10830 
10831 
10832 /*---------------------------------------------------------------------------*/
10833 /* Variable declarations */
10834 /*---------------------------------------------------------------------------*/
10835 
10836 //#ifndef lint
10837 //static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.14 2012/02/05 01:07:19 fabio Exp $";
10838 //#endif
10839 
10840 /*---------------------------------------------------------------------------*/
10841 /* Macro declarations */
10842 /*---------------------------------------------------------------------------*/
10843 
10844 
10847 /*---------------------------------------------------------------------------*/
10848 /* Static function prototypes */
10849 /*---------------------------------------------------------------------------*/
10850 
10851 static void ddSuppInteract (DdNode *f, char *support);
10852 static void ddClearLocal (DdNode *f);
10853 static void ddUpdateInteract (DdManager *table, char *support);
10854 static void ddClearGlobal2 (DdManager *table);
10855 
10859 /*---------------------------------------------------------------------------*/
10860 /* Definition of exported functions */
10861 /*---------------------------------------------------------------------------*/
10862 
10863 
10864 /*---------------------------------------------------------------------------*/
10865 /* Definition of internal functions */
10866 /*---------------------------------------------------------------------------*/
10867 
10868 
10881 void
10883  DdManager * table,
10884  int x,
10885  int y)
10886 {
10887  int posn, word, bit;
10888 
10889 #ifdef DD_DEBUG
10890  assert(x < y);
10891  assert(y < table->size);
10892  assert(x >= 0);
10893 #endif
10894 
10895  posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
10896  word = posn >> LOGBPL;
10897  bit = posn & (BPL-1);
10898  table->interact[word] |= 1L << bit;
10899 
10900 } /* end of cuddSetInteract */
10901 
10902 
10916 int
10918  DdManager * table,
10919  int x,
10920  int y)
10921 {
10922  int posn, word, bit, result;
10923 
10924  if (x > y) {
10925  int tmp = x;
10926  x = y;
10927  y = tmp;
10928  }
10929 #ifdef DD_DEBUG
10930  assert(x < y);
10931  assert(y < table->size);
10932  assert(x >= 0);
10933 #endif
10934 
10935  posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
10936  word = posn >> LOGBPL;
10937  bit = posn & (BPL-1);
10938  result = (table->interact[word] >> bit) & 1L;
10939  return(result);
10940 
10941 } /* end of cuddTestInteract */
10942 
10943 
10962 int
10964  DdManager * table)
10965 {
10966  int i,j;
10967  unsigned long words;
10968  long *interact;
10969  char *support;
10970  DdNode *f;
10971  DdNode *sentinel = &(table->sentinel);
10972  DdNodePtr *nodelist;
10973  int slots;
10974  unsigned long n = (unsigned long) table->size;
10975 
10976  words = ((n * (n-1)) >> (1 + LOGBPL)) + 1;
10977  table->interact = interact = ALLOC(long,words);
10978  if (interact == NULL) {
10979  table->errorCode = CUDD_MEMORY_OUT;
10980  return(0);
10981  }
10982  for (i = 0; i < words; i++) {
10983  interact[i] = 0;
10984  }
10985 
10986  support = ALLOC(char,n);
10987  if (support == NULL) {
10988  table->errorCode = CUDD_MEMORY_OUT;
10989  FREE(interact);
10990  return(0);
10991  }
10992  for (i = 0; i < n; i++) {
10993  support[i] = 0;
10994  }
10995 
10996  for (i = 0; i < n; i++) {
10997  nodelist = table->subtables[i].nodelist;
10998  slots = table->subtables[i].slots;
10999  for (j = 0; j < slots; j++) {
11000  f = nodelist[j];
11001  while (f != sentinel) {
11002  /* A node is a root of the DAG if it cannot be
11003  ** reached by nodes above it. If a node was never
11004  ** reached during the previous depth-first searches,
11005  ** then it is a root, and we start a new depth-first
11006  ** search from it.
11007  */
11008  if (!Cudd_IsComplement(f->next)) {
11009  ddSuppInteract(f,support);
11010  ddClearLocal(f);
11011  ddUpdateInteract(table,support);
11012  }
11013  f = Cudd_Regular(f->next);
11014  }
11015  }
11016  }
11017  ddClearGlobal2(table);
11018 
11019  FREE(support);
11020  return(1);
11021 
11022 } /* end of cuddInitInteract */
11023 
11024 
11025 /*---------------------------------------------------------------------------*/
11026 /* Definition of static functions */
11027 /*---------------------------------------------------------------------------*/
11028 
11029 
11042 static void
11044  DdNode * f,
11045  char * support)
11046 {
11047  if (cuddIsConstant(f) || Cudd_IsComplement(cuddT(f))) {
11048  return;
11049  }
11050 
11051  support[f->index] = 1;
11052  ddSuppInteract(cuddT(f),support);
11053  ddSuppInteract(Cudd_Regular(cuddE(f)),support);
11054  /* mark as visited */
11055  cuddT(f) = Cudd_Complement(cuddT(f));
11056  f->next = Cudd_Complement(f->next);
11057  return;
11058 
11059 } /* end of ddSuppInteract */
11060 
11061 
11073 static void
11075  DdNode * f)
11076 {
11077  if (cuddIsConstant(f) || !Cudd_IsComplement(cuddT(f))) {
11078  return;
11079  }
11080  /* clear visited flag */
11081  cuddT(f) = Cudd_Regular(cuddT(f));
11082  ddClearLocal(cuddT(f));
11084  return;
11085 
11086 } /* end of ddClearLocal */
11087 
11088 
11102 static void
11104  DdManager * table,
11105  char * support)
11106 {
11107  int i,j;
11108  int n = table->size;
11109 
11110  for (i = 0; i < n-1; i++) {
11111  if (support[i] == 1) {
11112  support[i] = 0;
11113  for (j = i+1; j < n; j++) {
11114  if (support[j] == 1) {
11115  cuddSetInteract(table,i,j);
11116  }
11117  }
11118  }
11119  }
11120  support[n-1] = 0;
11121 
11122 } /* end of ddUpdateInteract */
11123 
11124 
11138 static void
11140  DdManager * table)
11141 {
11142  int i,j;
11143  DdNode *f;
11144  DdNode *sentinel = &(table->sentinel);
11145  DdNodePtr *nodelist;
11146  int slots;
11147 
11148  for (i = 0; i < table->size; i++) {
11149  nodelist = table->subtables[i].nodelist;
11150  slots = table->subtables[i].slots;
11151  for (j = 0; j < slots; j++) {
11152  f = nodelist[j];
11153  while (f != sentinel) {
11154  f->next = Cudd_Regular(f->next);
11155  f = f->next;
11156  }
11157  }
11158  }
11159 
11160 } /* end of ddClearGlobal */
11161 
11240 /*---------------------------------------------------------------------------*/
11241 /* Constant declarations */
11242 /*---------------------------------------------------------------------------*/
11243 
11244 #define DD_MAX_HASHTABLE_DENSITY 2 /* tells when to resize a table */
11245 
11246 /*---------------------------------------------------------------------------*/
11247 /* Stucture declarations */
11248 /*---------------------------------------------------------------------------*/
11249 
11250 
11251 /*---------------------------------------------------------------------------*/
11252 /* Type declarations */
11253 /*---------------------------------------------------------------------------*/
11254 
11255 
11256 /*---------------------------------------------------------------------------*/
11257 /* Variable declarations */
11258 /*---------------------------------------------------------------------------*/
11259 
11260 //#ifndef lint
11261 //static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.27 2012/02/05 01:07:19 fabio Exp $";
11262 //#endif
11263 
11264 /*---------------------------------------------------------------------------*/
11265 /* Macro declarations */
11266 /*---------------------------------------------------------------------------*/
11267 
11279 #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
11280 #define ddLCHash1(f,shift) \
11281 (((unsigned)(ptruint)(f) * DD_P1) >> (shift))
11282 #else
11283 #define ddLCHash1(f,shift) \
11284 (((unsigned)(f) * DD_P1) >> (shift))
11285 #endif
11286 
11287 
11299 #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
11300 #define ddLCHash2(f,g,shift) \
11301 ((((unsigned)(ptruint)(f) * DD_P1 + \
11302  (unsigned)(ptruint)(g)) * DD_P2) >> (shift))
11303 #else
11304 #define ddLCHash2(f,g,shift) \
11305 ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift))
11306 #endif
11307 
11308 
11320 #define ddLCHash3(f,g,h,shift) ddCHash2(f,g,h,shift)
11321 
11322 
11325 /*---------------------------------------------------------------------------*/
11326 /* Static function prototypes */
11327 /*---------------------------------------------------------------------------*/
11328 
11329 static void cuddLocalCacheResize (DdLocalCache *cache);
11330 DD_INLINE static unsigned int ddLCHash (DdNodePtr *key, unsigned int keysize, int shift);
11331 static void cuddLocalCacheAddToList (DdLocalCache *cache);
11332 static void cuddLocalCacheRemoveFromList (DdLocalCache *cache);
11333 static int cuddHashTableResize (DdHashTable *hash);
11335 
11339 /*---------------------------------------------------------------------------*/
11340 /* Definition of exported functions */
11341 /*---------------------------------------------------------------------------*/
11342 
11343 /*---------------------------------------------------------------------------*/
11344 /* Definition of internal functions */
11345 /*---------------------------------------------------------------------------*/
11346 
11347 
11348 
11361 void
11363  DdManager * manager)
11364 {
11365  DdLocalCache *cache = manager->localCaches;
11366  unsigned int keysize;
11367  unsigned int itemsize;
11368  unsigned int slots;
11369  DdLocalCacheItem *item;
11370  DdNodePtr *key;
11371  unsigned int i, j;
11372 
11373  while (cache != NULL) {
11374  keysize = cache->keysize;
11375  itemsize = cache->itemsize;
11376  slots = cache->slots;
11377  item = cache->item;
11378  for (i = 0; i < slots; i++) {
11379  if (item->value != NULL) {
11380  if (Cudd_Regular(item->value)->ref == 0) {
11381  item->value = NULL;
11382  } else {
11383  key = item->key;
11384  for (j = 0; j < keysize; j++) {
11385  if (Cudd_Regular(key[j])->ref == 0) {
11386  item->value = NULL;
11387  break;
11388  }
11389  }
11390  }
11391  }
11392  item = (DdLocalCacheItem *) ((char *) item + itemsize);
11393  }
11394  cache = cache->next;
11395  }
11396  return;
11397 
11398 } /* end of cuddLocalCacheClearDead */
11399 
11400 
11413 void
11415  DdManager * manager)
11416 {
11417  DdLocalCache *cache = manager->localCaches;
11418 
11419  while (cache != NULL) {
11420  memset(cache->item, 0, cache->slots * cache->itemsize);
11421  cache = cache->next;
11422  }
11423  return;
11424 
11425 } /* end of cuddLocalCacheClearAll */
11426 
11427 
11428 #ifdef DD_CACHE_PROFILE
11429 
11430 #define DD_HYSTO_BINS 8
11431 
11444 int
11445 cuddLocalCacheProfile(
11446  DdLocalCache * cache)
11447 {
11448  double count, mean, meansq, stddev, expected;
11449  long max, min;
11450  int imax, imin;
11451  int i, retval, slots;
11452  long *hystogram;
11453  int nbins = DD_HYSTO_BINS;
11454  int bin;
11455  long thiscount;
11456  double totalcount;
11457  int nzeroes;
11459  FILE *fp = cache->manager->out;
11460 
11461  slots = cache->slots;
11462 
11463  meansq = mean = expected = 0.0;
11464  max = min = (long) cache->item[0].count;
11465  imax = imin = nzeroes = 0;
11466  totalcount = 0.0;
11467 
11468  hystogram = ALLOC(long, nbins);
11469  if (hystogram == NULL) {
11470  return(0);
11471  }
11472  for (i = 0; i < nbins; i++) {
11473  hystogram[i] = 0;
11474  }
11475 
11476  for (i = 0; i < slots; i++) {
11477  entry = (DdLocalCacheItem *) ((char *) cache->item +
11478  i * cache->itemsize);
11479  thiscount = (long) entry->count;
11480  if (thiscount > max) {
11481  max = thiscount;
11482  imax = i;
11483  }
11484  if (thiscount < min) {
11485  min = thiscount;
11486  imin = i;
11487  }
11488  if (thiscount == 0) {
11489  nzeroes++;
11490  }
11491  count = (double) thiscount;
11492  mean += count;
11493  meansq += count * count;
11494  totalcount += count;
11495  expected += count * (double) i;
11496  bin = (i * nbins) / slots;
11497  hystogram[bin] += thiscount;
11498  }
11499  mean /= (double) slots;
11500  meansq /= (double) slots;
11501  stddev = sqrt(meansq - mean*mean);
11502 
11503  retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean);
11504  if (retval == EOF) return(0);
11505  retval = fprintf(fp,"standard deviation = %g\n", stddev);
11506  if (retval == EOF) return(0);
11507  retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
11508  if (retval == EOF) return(0);
11509  retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
11510  if (retval == EOF) return(0);
11511  retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes);
11512  if (retval == EOF) return(0);
11513 
11514  if (totalcount) {
11515  expected /= totalcount;
11516  retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
11517  if (retval == EOF) return(0);
11518  retval = fprintf(fp," (expected bin value = %g)\n# ", expected);
11519  if (retval == EOF) return(0);
11520  for (i = nbins - 1; i>=0; i--) {
11521  retval = fprintf(fp,"%ld ", hystogram[i]);
11522  if (retval == EOF) return(0);
11523  }
11524  retval = fprintf(fp,"\n");
11525  if (retval == EOF) return(0);
11526  }
11527 
11528  FREE(hystogram);
11529  return(1);
11530 
11531 } /* end of cuddLocalCacheProfile */
11532 #endif
11533 
11534 
11547 DdHashTable *
11549  DdManager * manager,
11550  unsigned int keySize,
11551  unsigned int initSize)
11552 {
11553  DdHashTable *hash;
11554  int logSize;
11555 
11556  hash = ALLOC(DdHashTable, 1);
11557  if (hash == NULL) {
11558  manager->errorCode = CUDD_MEMORY_OUT;
11559  return(NULL);
11560  }
11561  hash->keysize = keySize;
11562  hash->manager = manager;
11563  hash->memoryList = NULL;
11564  hash->nextFree = NULL;
11565  hash->itemsize = (keySize + 1) * sizeof(DdNode *) +
11566  sizeof(ptrint) + sizeof(DdHashItem *);
11567  /* We have to guarantee that the shift be < 32. */
11568  if (initSize < 2) initSize = 2;
11569  logSize = cuddComputeFloorLog2(initSize);
11570  hash->numBuckets = 1 << logSize;
11571  hash->shift = sizeof(int) * 8 - logSize;
11572  hash->bucket = ALLOC(DdHashItem *, hash->numBuckets);
11573  if (hash->bucket == NULL) {
11574  manager->errorCode = CUDD_MEMORY_OUT;
11575  FREE(hash);
11576  return(NULL);
11577  }
11578  memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *));
11579  hash->size = 0;
11581  return(hash);
11582 
11583 } /* end of cuddHashTableInit */
11584 
11585 
11597 void
11599  DdHashTable * hash)
11600 {
11601  unsigned int i;
11602  DdManager *dd = hash->manager;
11603  DdHashItem *bucket;
11604  DdHashItem **memlist, **nextmem;
11605  unsigned int numBuckets = hash->numBuckets;
11606 
11607  for (i = 0; i < numBuckets; i++) {
11608  bucket = hash->bucket[i];
11609  while (bucket != NULL) {
11610  Cudd_RecursiveDeref(dd, bucket->value);
11611  bucket = bucket->next;
11612  }
11613  }
11614 
11615  memlist = hash->memoryList;
11616  while (memlist != NULL) {
11617  nextmem = (DdHashItem **) memlist[0];
11618  FREE(memlist);
11619  memlist = nextmem;
11620  }
11621 
11622  FREE(hash->bucket);
11623  FREE(hash);
11624 
11625  return;
11626 
11627 } /* end of cuddHashTableQuit */
11628 
11629 
11642 void
11644  DdHashTable * hash)
11645 {
11646 #ifdef __osf__
11647  #pragma pointer_size save
11648 #pragma pointer_size short
11649 #endif
11650  DdHashItem **memlist, **nextmem;
11651 
11652  memlist = hash->memoryList;
11653  while (memlist != NULL) {
11654  nextmem = (DdHashItem **) memlist[0];
11655  FREE(memlist);
11656  memlist = nextmem;
11657  }
11658 
11659  FREE(hash->bucket);
11660  FREE(hash);
11661 #ifdef __osf__
11662 #pragma pointer_size restore
11663 #endif
11664 
11665  return;
11666 
11667 } /* end of cuddHashTableGenericQuit */
11668 
11669 
11683 int
11685  DdHashTable * hash,
11686  DdNodePtr * key,
11687  DdNode * value,
11688  ptrint count)
11689 {
11690  int result;
11691  unsigned int posn;
11692  DdHashItem *item;
11693  unsigned int i;
11694 
11695 #ifdef DD_DEBUG
11696  assert(hash->keysize > 3);
11697 #endif
11698 
11699  if (hash->size > hash->maxsize) {
11700  result = cuddHashTableResize(hash);
11701  if (result == 0) return(0);
11702  }
11703  item = cuddHashTableAlloc(hash);
11704  if (item == NULL) return(0);
11705  hash->size++;
11706  item->value = value;
11707  cuddRef(value);
11708  item->count = count;
11709  for (i = 0; i < hash->keysize; i++) {
11710  item->key[i] = key[i];
11711  }
11712  posn = ddLCHash(key,hash->keysize,hash->shift);
11713  item->next = hash->bucket[posn];
11714  hash->bucket[posn] = item;
11715 
11716  return(1);
11717 
11718 } /* end of cuddHashTableInsert */
11719 
11720 
11738 DdNode *
11740  DdHashTable * hash,
11741  DdNodePtr * key)
11742 {
11743  unsigned int posn;
11744  DdHashItem *item, *prev;
11745  unsigned int i, keysize;
11746 
11747 #ifdef DD_DEBUG
11748  assert(hash->keysize > 3);
11749 #endif
11750 
11751  posn = ddLCHash(key,hash->keysize,hash->shift);
11752  item = hash->bucket[posn];
11753  prev = NULL;
11754 
11755  keysize = hash->keysize;
11756  while (item != NULL) {
11757  DdNodePtr *key2 = item->key;
11758  int equal = 1;
11759  for (i = 0; i < keysize; i++) {
11760  if (key[i] != key2[i]) {
11761  equal = 0;
11762  break;
11763  }
11764  }
11765  if (equal) {
11766  DdNode *value = item->value;
11767  cuddSatDec(item->count);
11768  if (item->count == 0) {
11769  cuddDeref(value);
11770  if (prev == NULL) {
11771  hash->bucket[posn] = item->next;
11772  } else {
11773  prev->next = item->next;
11774  }
11775  item->next = hash->nextFree;
11776  hash->nextFree = item;
11777  hash->size--;
11778  }
11779  return(value);
11780  }
11781  prev = item;
11782  item = item->next;
11783  }
11784  return(NULL);
11785 
11786 } /* end of cuddHashTableLookup */
11787 
11788 
11802 int
11804  DdHashTable * hash,
11805  DdNode * f,
11806  DdNode * value,
11807  ptrint count)
11808 {
11809  int result;
11810  unsigned int posn;
11811  DdHashItem *item;
11812 
11813 #ifdef DD_DEBUG
11814  assert(hash->keysize == 1);
11815 #endif
11816 
11817  if (hash->size > hash->maxsize) {
11818  result = cuddHashTableResize(hash);
11819  if (result == 0) return(0);
11820  }
11821  item = cuddHashTableAlloc(hash);
11822  if (item == NULL) return(0);
11823  hash->size++;
11824  item->value = value;
11825  cuddRef(value);
11826  item->count = count;
11827  item->key[0] = f;
11828  posn = ddLCHash1(f,hash->shift);
11829  item->next = hash->bucket[posn];
11830  hash->bucket[posn] = item;
11831 
11832  return(1);
11833 
11834 } /* end of cuddHashTableInsert1 */
11835 
11836 
11854 DdNode *
11856  DdHashTable * hash,
11857  DdNode * f)
11858 {
11859  unsigned int posn;
11860  DdHashItem *item, *prev;
11861 
11862 #ifdef DD_DEBUG
11863  assert(hash->keysize == 1);
11864 #endif
11865 
11866  posn = ddLCHash1(f,hash->shift);
11867  item = hash->bucket[posn];
11868  prev = NULL;
11869 
11870  while (item != NULL) {
11871  DdNodePtr *key = item->key;
11872  if (f == key[0]) {
11873  DdNode *value = item->value;
11874  cuddSatDec(item->count);
11875  if (item->count == 0) {
11876  cuddDeref(value);
11877  if (prev == NULL) {
11878  hash->bucket[posn] = item->next;
11879  } else {
11880  prev->next = item->next;
11881  }
11882  item->next = hash->nextFree;
11883  hash->nextFree = item;
11884  hash->size--;
11885  }
11886  return(value);
11887  }
11888  prev = item;
11889  item = item->next;
11890  }
11891  return(NULL);
11892 
11893 } /* end of cuddHashTableLookup1 */
11894 
11895 
11909 int
11911  DdHashTable * hash,
11912  DdNode * f,
11913  void * value)
11914 {
11915  int result;
11916  unsigned int posn;
11917  DdHashItem *item;
11918 
11919 #ifdef DD_DEBUG
11920  assert(hash->keysize == 1);
11921 #endif
11922 
11923  if (hash->size > hash->maxsize) {
11924  result = cuddHashTableResize(hash);
11925  if (result == 0) return(0);
11926  }
11927  item = cuddHashTableAlloc(hash);
11928  if (item == NULL) return(0);
11929  hash->size++;
11930  item->value = (DdNode *) value;
11931  item->count = 0;
11932  item->key[0] = f;
11933  posn = ddLCHash1(f,hash->shift);
11934  item->next = hash->bucket[posn];
11935  hash->bucket[posn] = item;
11936 
11937  return(1);
11938 
11939 } /* end of cuddHashTableGenericInsert */
11940 
11941 
11956 void *
11958  DdHashTable * hash,
11959  DdNode * f)
11960 {
11961  unsigned int posn;
11962  DdHashItem *item;
11963 
11964 #ifdef DD_DEBUG
11965  assert(hash->keysize == 1);
11966 #endif
11967 
11968  posn = ddLCHash1(f,hash->shift);
11969  item = hash->bucket[posn];
11970 
11971  while (item != NULL) {
11972  if (f == item->key[0]) {
11973  return ((void *) item->value);
11974  }
11975  item = item->next;
11976  }
11977  return(NULL);
11978 
11979 } /* end of cuddHashTableGenericLookup */
11980 
11981 
11995 int
11997  DdHashTable * hash,
11998  DdNode * f,
11999  DdNode * g,
12000  DdNode * value,
12001  ptrint count)
12002 {
12003  int result;
12004  unsigned int posn;
12005  DdHashItem *item;
12006 
12007 #ifdef DD_DEBUG
12008  assert(hash->keysize == 2);
12009 #endif
12010 
12011  if (hash->size > hash->maxsize) {
12012  result = cuddHashTableResize(hash);
12013  if (result == 0) return(0);
12014  }
12015  item = cuddHashTableAlloc(hash);
12016  if (item == NULL) return(0);
12017  hash->size++;
12018  item->value = value;
12019  cuddRef(value);
12020  item->count = count;
12021  item->key[0] = f;
12022  item->key[1] = g;
12023  posn = ddLCHash2(f,g,hash->shift);
12024  item->next = hash->bucket[posn];
12025  hash->bucket[posn] = item;
12026 
12027  return(1);
12028 
12029 } /* end of cuddHashTableInsert2 */
12030 
12031 
12049 DdNode *
12051  DdHashTable * hash,
12052  DdNode * f,
12053  DdNode * g)
12054 {
12055  unsigned int posn;
12056  DdHashItem *item, *prev;
12057 
12058 #ifdef DD_DEBUG
12059  assert(hash->keysize == 2);
12060 #endif
12061 
12062  posn = ddLCHash2(f,g,hash->shift);
12063  item = hash->bucket[posn];
12064  prev = NULL;
12065 
12066  while (item != NULL) {
12067  DdNodePtr *key = item->key;
12068  if ((f == key[0]) && (g == key[1])) {
12069  DdNode *value = item->value;
12070  cuddSatDec(item->count);
12071  if (item->count == 0) {
12072  cuddDeref(value);
12073  if (prev == NULL) {
12074  hash->bucket[posn] = item->next;
12075  } else {
12076  prev->next = item->next;
12077  }
12078  item->next = hash->nextFree;
12079  hash->nextFree = item;
12080  hash->size--;
12081  }
12082  return(value);
12083  }
12084  prev = item;
12085  item = item->next;
12086  }
12087  return(NULL);
12088 
12089 } /* end of cuddHashTableLookup2 */
12090 
12091 
12105 int
12107  DdHashTable * hash,
12108  DdNode * f,
12109  DdNode * g,
12110  DdNode * h,
12111  DdNode * value,
12112  ptrint count)
12113 {
12114  int result;
12115  unsigned int posn;
12116  DdHashItem *item;
12117 
12118 #ifdef DD_DEBUG
12119  assert(hash->keysize == 3);
12120 #endif
12121 
12122  if (hash->size > hash->maxsize) {
12123  result = cuddHashTableResize(hash);
12124  if (result == 0) return(0);
12125  }
12126  item = cuddHashTableAlloc(hash);
12127  if (item == NULL) return(0);
12128  hash->size++;
12129  item->value = value;
12130  cuddRef(value);
12131  item->count = count;
12132  item->key[0] = f;
12133  item->key[1] = g;
12134  item->key[2] = h;
12135  posn = ddLCHash3(f,g,h,hash->shift);
12136  item->next = hash->bucket[posn];
12137  hash->bucket[posn] = item;
12138 
12139  return(1);
12140 
12141 } /* end of cuddHashTableInsert3 */
12142 
12143 
12161 DdNode *
12163  DdHashTable * hash,
12164  DdNode * f,
12165  DdNode * g,
12166  DdNode * h)
12167 {
12168  unsigned int posn;
12169  DdHashItem *item, *prev;
12170 
12171 #ifdef DD_DEBUG
12172  assert(hash->keysize == 3);
12173 #endif
12174 
12175  posn = ddLCHash3(f,g,h,hash->shift);
12176  item = hash->bucket[posn];
12177  prev = NULL;
12178 
12179  while (item != NULL) {
12180  DdNodePtr *key = item->key;
12181  if ((f == key[0]) && (g == key[1]) && (h == key[2])) {
12182  DdNode *value = item->value;
12183  cuddSatDec(item->count);
12184  if (item->count == 0) {
12185  cuddDeref(value);
12186  if (prev == NULL) {
12187  hash->bucket[posn] = item->next;
12188  } else {
12189  prev->next = item->next;
12190  }
12191  item->next = hash->nextFree;
12192  hash->nextFree = item;
12193  hash->size--;
12194  }
12195  return(value);
12196  }
12197  prev = item;
12198  item = item->next;
12199  }
12200  return(NULL);
12201 
12202 } /* end of cuddHashTableLookup3 */
12203 
12204 
12205 /*---------------------------------------------------------------------------*/
12206 /* Definition of static functions */
12207 /*---------------------------------------------------------------------------*/
12208 
12209 
12221 static void
12223  DdLocalCache * cache)
12224 {
12225  DdLocalCacheItem *item, *olditem, *entry, *old;
12226  int i, shift;
12227  unsigned int posn;
12228  unsigned int slots, oldslots;
12229  extern DD_OOMFP MMoutOfMemory;
12230  DD_OOMFP saveHandler;
12231 
12232  olditem = cache->item;
12233  oldslots = cache->slots;
12234  slots = cache->slots = oldslots << 1;
12235 
12236 #ifdef DD_VERBOSE
12237  (void) fprintf(cache->manager->err,
12238  "Resizing local cache from %d to %d entries\n",
12239  oldslots, slots);
12240  (void) fprintf(cache->manager->err,
12241  "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n",
12242  cache->hits, cache->lookUps, cache->hits / cache->lookUps);
12243 #endif
12244 
12245  saveHandler = MMoutOfMemory;
12246  MMoutOfMemory = Cudd_OutOfMem;
12247  cache->item = item =
12248  (DdLocalCacheItem *) ALLOC(char, slots * cache->itemsize);
12249  MMoutOfMemory = saveHandler;
12250  /* If we fail to allocate the new table we just give up. */
12251  if (item == NULL) {
12252 #ifdef DD_VERBOSE
12253  (void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n");
12254 #endif
12255  cache->slots = oldslots;
12256  cache->item = olditem;
12257  /* Do not try to resize again. */
12258  cache->maxslots = oldslots - 1;
12259  return;
12260  }
12261  shift = --(cache->shift);
12262  cache->manager->memused += (slots - oldslots) * cache->itemsize;
12263 
12264  /* Clear new cache. */
12265  memset(item, 0, slots * cache->itemsize);
12266 
12267  /* Copy from old cache to new one. */
12268  for (i = 0; (unsigned) i < oldslots; i++) {
12269  old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize);
12270  if (old->value != NULL) {
12271  posn = ddLCHash(old->key,cache->keysize,shift);
12272  entry = (DdLocalCacheItem *) ((char *) item +
12273  posn * cache->itemsize);
12274  memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *));
12275  entry->value = old->value;
12276  }
12277  }
12278 
12279  FREE(olditem);
12280 
12281  /* Reinitialize measurements so as to avoid division by 0 and
12282  ** immediate resizing.
12283  */
12284  cache->lookUps = (double) (int) (slots * cache->minHit + 1);
12285  cache->hits = 0;
12286 
12287 } /* end of cuddLocalCacheResize */
12288 
12289 
12302 DD_INLINE
12303 static unsigned int
12305  DdNodePtr * key,
12306  unsigned int keysize,
12307  int shift)
12308 {
12309  unsigned int val = (unsigned int) (ptrint) key[0] * DD_P2;
12310  unsigned int i;
12311 
12312  for (i = 1; i < keysize; i++) {
12313  val = val * DD_P1 + (int) (ptrint) key[i];
12314  }
12315 
12316  return(val >> shift);
12317 
12318 } /* end of ddLCHash */
12319 
12320 
12332 static void
12334  DdLocalCache * cache)
12335 {
12336  DdManager *manager = cache->manager;
12337 
12338  cache->next = manager->localCaches;
12339  manager->localCaches = cache;
12340  return;
12341 
12342 } /* end of cuddLocalCacheAddToList */
12343 
12344 
12356 static void
12358  DdLocalCache * cache)
12359 {
12360  DdManager *manager = cache->manager;
12361  DdLocalCache **prevCache, *nextCache;
12362 
12363  prevCache = &(manager->localCaches);
12364  nextCache = manager->localCaches;
12365 
12366  while (nextCache != NULL) {
12367  if (nextCache == cache) {
12368  *prevCache = nextCache->next;
12369  return;
12370  }
12371  prevCache = &(nextCache->next);
12372  nextCache = nextCache->next;
12373  }
12374  return; /* should never get here */
12375 
12376 } /* end of cuddLocalCacheRemoveFromList */
12377 
12378 
12391 static int
12393  DdHashTable * hash)
12394 {
12395  int j;
12396  unsigned int posn;
12397  DdHashItem *item;
12398  DdHashItem *next;
12399  DdNode **key;
12400  int numBuckets;
12401  DdHashItem **buckets;
12402  DdHashItem **oldBuckets = hash->bucket;
12403  int shift;
12404  int oldNumBuckets = hash->numBuckets;
12405  extern DD_OOMFP MMoutOfMemory;
12406  DD_OOMFP saveHandler;
12407 
12408  /* Compute the new size of the table. */
12409  numBuckets = oldNumBuckets << 1;
12410  saveHandler = MMoutOfMemory;
12411  MMoutOfMemory = Cudd_OutOfMem;
12412  buckets = ALLOC(DdHashItem *, numBuckets);
12413  MMoutOfMemory = saveHandler;
12414  if (buckets == NULL) {
12415  hash->maxsize <<= 1;
12416  return(1);
12417  }
12418 
12419  hash->bucket = buckets;
12420  hash->numBuckets = numBuckets;
12421  shift = --(hash->shift);
12422  hash->maxsize <<= 1;
12423  memset(buckets, 0, numBuckets * sizeof(DdHashItem *));
12424  if (hash->keysize == 1) {
12425  for (j = 0; j < oldNumBuckets; j++) {
12426  item = oldBuckets[j];
12427  while (item != NULL) {
12428  next = item->next;
12429  key = item->key;
12430  posn = ddLCHash2(key[0], key[0], shift);
12431  item->next = buckets[posn];
12432  buckets[posn] = item;
12433  item = next;
12434  }
12435  }
12436  } else if (hash->keysize == 2) {
12437  for (j = 0; j < oldNumBuckets; j++) {
12438  item = oldBuckets[j];
12439  while (item != NULL) {
12440  next = item->next;
12441  key = item->key;
12442  posn = ddLCHash2(key[0], key[1], shift);
12443  item->next = buckets[posn];
12444  buckets[posn] = item;
12445  item = next;
12446  }
12447  }
12448  } else if (hash->keysize == 3) {
12449  for (j = 0; j < oldNumBuckets; j++) {
12450  item = oldBuckets[j];
12451  while (item != NULL) {
12452  next = item->next;
12453  key = item->key;
12454  posn = ddLCHash3(key[0], key[1], key[2], shift);
12455  item->next = buckets[posn];
12456  buckets[posn] = item;
12457  item = next;
12458  }
12459  }
12460  } else {
12461  for (j = 0; j < oldNumBuckets; j++) {
12462  item = oldBuckets[j];
12463  while (item != NULL) {
12464  next = item->next;
12465  posn = ddLCHash(item->key, hash->keysize, shift);
12466  item->next = buckets[posn];
12467  buckets[posn] = item;
12468  item = next;
12469  }
12470  }
12471  }
12472  FREE(oldBuckets);
12473  return(1);
12474 
12475 } /* end of cuddHashTableResize */
12476 
12477 
12492 DD_INLINE
12493 static DdHashItem *
12495  DdHashTable * hash)
12496 {
12497 int i;
12498 unsigned int itemsize = hash->itemsize;
12499 extern DD_OOMFP MMoutOfMemory;
12500 DD_OOMFP saveHandler;
12501 DdHashItem **mem, *thisOne, *next, *item;
12502 
12503 if (hash->nextFree == NULL) {
12504 saveHandler = MMoutOfMemory;
12505 MMoutOfMemory = Cudd_OutOfMem;
12506 mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize);
12507 MMoutOfMemory = saveHandler;
12508 if (mem == NULL) {
12509 if (hash->manager->stash != NULL) {
12510 FREE(hash->manager->stash);
12511 hash->manager->stash = NULL;
12512 /* Inhibit resizing of tables. */
12513 hash->manager->maxCacheHard = hash->manager->cacheSlots - 1;
12514 hash->manager->cacheSlack = - (int) (hash->manager->cacheSlots + 1);
12515 for (i = 0; i < hash->manager->size; i++) {
12516 hash->manager->subtables[i].maxKeys <<= 2;
12517 }
12518 hash->manager->gcFrac = 0.2;
12519 hash->manager->minDead =
12520 (unsigned) (0.2 * (double) hash->manager->slots);
12521 mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize);
12522 }
12523 if (mem == NULL) {
12524 (*MMoutOfMemory)((long)((DD_MEM_CHUNK + 1) * itemsize));
12526 return(NULL);
12527 }
12528 }
12529 
12530 mem[0] = (DdHashItem *) hash->memoryList;
12531 hash->memoryList = mem;
12532 
12533 thisOne = (DdHashItem *) ((char *) mem + itemsize);
12534 hash->nextFree = thisOne;
12535 for (i = 1; i < DD_MEM_CHUNK; i++) {
12536 next = (DdHashItem *) ((char *) thisOne + itemsize);
12537 thisOne->next = next;
12538 thisOne = next;
12539 }
12540 
12541 thisOne->next = NULL;
12542 
12543 }
12544 item = hash->nextFree;
12545 hash->nextFree = item->next;
12546 return(item);
12547 
12548 } /* end of cuddHashTableAlloc */
12613 /*---------------------------------------------------------------------------*/
12614 /* Constant declarations */
12615 /*---------------------------------------------------------------------------*/
12616 
12617 #define CUDD_SWAP_MOVE 0
12618 #define CUDD_LINEAR_TRANSFORM_MOVE 1
12619 #define CUDD_INVERSE_TRANSFORM_MOVE 2
12620 #if SIZEOF_LONG == 8
12621 #define BPL 64
12622 #define LOGBPL 6
12623 #else
12624 #define BPL 32
12625 #define LOGBPL 5
12626 #endif
12627 
12628 /*---------------------------------------------------------------------------*/
12629 /* Stucture declarations */
12630 /*---------------------------------------------------------------------------*/
12631 
12632 /*---------------------------------------------------------------------------*/
12633 /* Type declarations */
12634 /*---------------------------------------------------------------------------*/
12635 
12636 /*---------------------------------------------------------------------------*/
12637 /* Variable declarations */
12638 /*---------------------------------------------------------------------------*/
12639 
12640 //#ifndef lint
12641 //static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.29 2012/02/05 01:07:19 fabio Exp $";
12642 //#endif
12643 
12644 static int *entry;
12645 
12646 #ifdef DD_STATS
12647 extern int ddTotalNumberSwapping;
12648 extern int ddTotalNISwaps;
12649 static int ddTotalNumberLinearTr;
12650 #endif
12651 
12652 #ifdef DD_DEBUG
12653 static int zero = 0;
12654 #endif
12655 
12656 /*---------------------------------------------------------------------------*/
12657 /* Macro declarations */
12658 /*---------------------------------------------------------------------------*/
12659 
12662 /*---------------------------------------------------------------------------*/
12663 /* Static function prototypes */
12664 /*---------------------------------------------------------------------------*/
12665 
12666 static int ddLinearUniqueCompare (int *ptrX, int *ptrY);
12667 static int ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh);
12668 static Move * ddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves);
12669 static Move * ddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves);
12670 static int ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves);
12671 static Move* ddUndoMoves (DdManager *table, Move *moves);
12672 static void cuddXorLinear (DdManager *table, int x, int y);
12673 
12677 /*---------------------------------------------------------------------------*/
12678 /* Definition of exported functions */
12679 /*---------------------------------------------------------------------------*/
12680 
12681 
12694 int
12696  DdManager * table)
12697 {
12698  int i,j,k;
12699  int retval;
12700  int nvars = table->linearSize;
12701  int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
12702  long word;
12703 
12704  for (i = 0; i < nvars; i++) {
12705  for (j = 0; j < wordsPerRow; j++) {
12706  word = table->linear[i*wordsPerRow + j];
12707  for (k = 0; k < BPL; k++) {
12708  retval = fprintf(table->out,"%ld",word & 1);
12709  if (retval == 0) return(0);
12710  word >>= 1;
12711  }
12712  }
12713  retval = fprintf(table->out,"\n");
12714  if (retval == 0) return(0);
12715  }
12716  return(1);
12717 
12718 } /* end of Cudd_PrintLinear */
12719 
12720 
12721 
12722 /*---------------------------------------------------------------------------*/
12723 /* Definition of internal functions */
12724 /*---------------------------------------------------------------------------*/
12725 
12726 
12749 int
12751  DdManager * table,
12752  int lower,
12753  int upper)
12754 {
12755  int i;
12756  int *var;
12757  int size;
12758  int x;
12759  int result;
12760 #ifdef DD_STATS
12761  int previousSize;
12762 #endif
12763 
12764 #ifdef DD_STATS
12765  ddTotalNumberLinearTr = 0;
12766 #endif
12767 
12768  size = table->size;
12769 
12770  var = NULL;
12771  entry = NULL;
12772  if (table->linear == NULL) {
12773  result = cuddInitLinear(table);
12774  if (result == 0) goto cuddLinearAndSiftingOutOfMem;
12775 #if 0
12776  (void) fprintf(table->out,"\n");
12777  result = Cudd_PrintLinear(table);
12778  if (result == 0) goto cuddLinearAndSiftingOutOfMem;
12779 #endif
12780  } else if (table->size != table->linearSize) {
12781  result = cuddResizeLinear(table);
12782  if (result == 0) goto cuddLinearAndSiftingOutOfMem;
12783 #if 0
12784  (void) fprintf(table->out,"\n");
12785  result = Cudd_PrintLinear(table);
12786  if (result == 0) goto cuddLinearAndSiftingOutOfMem;
12787 #endif
12788  }
12789 
12790  /* Find order in which to sift variables. */
12791  entry = ALLOC(int,size);
12792  if (entry == NULL) {
12793  table->errorCode = CUDD_MEMORY_OUT;
12794  goto cuddLinearAndSiftingOutOfMem;
12795  }
12796  var = ALLOC(int,size);
12797  if (var == NULL) {
12798  table->errorCode = CUDD_MEMORY_OUT;
12799  goto cuddLinearAndSiftingOutOfMem;
12800  }
12801 
12802  for (i = 0; i < size; i++) {
12803  x = table->perm[i];
12804  entry[i] = table->subtables[x].keys;
12805  var[i] = i;
12806  }
12807 
12808  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare);
12809 
12810  /* Now sift. */
12811  for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
12812  x = table->perm[var[i]];
12813  if (x < lower || x > upper) continue;
12814 #ifdef DD_STATS
12815  previousSize = table->keys - table->isolated;
12816 #endif
12817  result = ddLinearAndSiftingAux(table,x,lower,upper);
12818  if (!result) goto cuddLinearAndSiftingOutOfMem;
12819 #ifdef DD_STATS
12820  if (table->keys < (unsigned) previousSize + table->isolated) {
12821  (void) fprintf(table->out,"-");
12822  } else if (table->keys > (unsigned) previousSize + table->isolated) {
12823  (void) fprintf(table->out,"+"); /* should never happen */
12824  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
12825  } else {
12826  (void) fprintf(table->out,"=");
12827  }
12828  fflush(table->out);
12829 #endif
12830 #ifdef DD_DEBUG
12831  (void) Cudd_DebugCheck(table);
12832 #endif
12833  }
12834 
12835  FREE(var);
12836  FREE(entry);
12837 
12838 #ifdef DD_STATS
12839  (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
12840  ddTotalNumberLinearTr);
12841 #endif
12842 
12843  return(1);
12844 
12845  cuddLinearAndSiftingOutOfMem:
12846 
12847  if (entry != NULL) FREE(entry);
12848  if (var != NULL) FREE(var);
12849 
12850  return(0);
12851 
12852 } /* end of cuddLinearAndSifting */
12853 
12854 
12873 int
12875  DdManager * table,
12876  int x,
12877  int y)
12878 {
12879  DdNodePtr *xlist, *ylist;
12880  int xindex, yindex;
12881  int xslots, yslots;
12882  int xshift, yshift;
12883  int oldxkeys, oldykeys;
12884  int newxkeys, newykeys;
12885  int comple, newcomplement;
12886  int i;
12887  int posn;
12888  int isolated;
12889  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
12890  DdNode *g,*next,*last;
12891  DdNodePtr *previousP;
12892  DdNode *tmp;
12893  DdNode *sentinel = &(table->sentinel);
12894 #ifdef DD_DEBUG
12895  int count, idcheck;
12896 #endif
12897 
12898 #ifdef DD_DEBUG
12899  assert(x < y);
12900  assert(cuddNextHigh(table,x) == y);
12901  assert(table->subtables[x].keys != 0);
12902  assert(table->subtables[y].keys != 0);
12903  assert(table->subtables[x].dead == 0);
12904  assert(table->subtables[y].dead == 0);
12905 #endif
12906 
12907  xindex = table->invperm[x];
12908  yindex = table->invperm[y];
12909 
12910  if (cuddTestInteract(table,xindex,yindex)) {
12911 #ifdef DD_STATS
12912  ddTotalNumberLinearTr++;
12913 #endif
12914  /* Get parameters of x subtable. */
12915  xlist = table->subtables[x].nodelist;
12916  oldxkeys = table->subtables[x].keys;
12917  xslots = table->subtables[x].slots;
12918  xshift = table->subtables[x].shift;
12919 
12920  /* Get parameters of y subtable. */
12921  ylist = table->subtables[y].nodelist;
12922  oldykeys = table->subtables[y].keys;
12923  yslots = table->subtables[y].slots;
12924  yshift = table->subtables[y].shift;
12925 
12926  newxkeys = 0;
12927  newykeys = oldykeys;
12928 
12929  /* Check whether the two projection functions involved in this
12930  ** swap are isolated. At the end, we'll be able to tell how many
12931  ** isolated projection functions are there by checking only these
12932  ** two functions again. This is done to eliminate the isolated
12933  ** projection functions from the node count.
12934  */
12935  isolated = - ((table->vars[xindex]->ref == 1) +
12936  (table->vars[yindex]->ref == 1));
12937 
12938  /* The nodes in the x layer are put in a chain.
12939  ** The chain is handled as a FIFO; g points to the beginning and
12940  ** last points to the end.
12941  */
12942  g = NULL;
12943 #ifdef DD_DEBUG
12944  last = NULL;
12945 #endif
12946  for (i = 0; i < xslots; i++) {
12947  f = xlist[i];
12948  if (f == sentinel) continue;
12949  xlist[i] = sentinel;
12950  if (g == NULL) {
12951  g = f;
12952  } else {
12953  last->next = f;
12954  }
12955  while ((next = f->next) != sentinel) {
12956  f = next;
12957  } /* while there are elements in the collision chain */
12958  last = f;
12959  } /* for each slot of the x subtable */
12960 #ifdef DD_DEBUG
12961  /* last is always assigned in the for loop because there is at
12962  ** least one key */
12963  assert(last != NULL);
12964 #endif
12965  last->next = NULL;
12966 
12967 #ifdef DD_COUNT
12968  table->swapSteps += oldxkeys;
12969 #endif
12970  /* Take care of the x nodes that must be re-expressed.
12971  ** They form a linked list pointed by g.
12972  */
12973  f = g;
12974  while (f != NULL) {
12975  next = f->next;
12976  /* Find f1, f0, f11, f10, f01, f00. */
12977  f1 = cuddT(f);
12978 #ifdef DD_DEBUG
12979  assert(!(Cudd_IsComplement(f1)));
12980 #endif
12981  if ((int) f1->index == yindex) {
12982  f11 = cuddT(f1); f10 = cuddE(f1);
12983  } else {
12984  f11 = f10 = f1;
12985  }
12986 #ifdef DD_DEBUG
12987  assert(!(Cudd_IsComplement(f11)));
12988 #endif
12989  f0 = cuddE(f);
12990  comple = Cudd_IsComplement(f0);
12991  f0 = Cudd_Regular(f0);
12992  if ((int) f0->index == yindex) {
12993  f01 = cuddT(f0); f00 = cuddE(f0);
12994  } else {
12995  f01 = f00 = f0;
12996  }
12997  if (comple) {
12998  f01 = Cudd_Not(f01);
12999  f00 = Cudd_Not(f00);
13000  }
13001  /* Decrease ref count of f1. */
13002  cuddSatDec(f1->ref);
13003  /* Create the new T child. */
13004  if (f11 == f00) {
13005  newf1 = f11;
13006  cuddSatInc(newf1->ref);
13007  } else {
13008  /* Check ylist for triple (yindex,f11,f00). */
13009  posn = ddHash(f11, f00, yshift);
13010  /* For each element newf1 in collision list ylist[posn]. */
13011  previousP = &(ylist[posn]);
13012  newf1 = *previousP;
13013  while (f11 < cuddT(newf1)) {
13014  previousP = &(newf1->next);
13015  newf1 = *previousP;
13016  }
13017  while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
13018  previousP = &(newf1->next);
13019  newf1 = *previousP;
13020  }
13021  if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
13022  cuddSatInc(newf1->ref);
13023  } else { /* no match */
13024  newf1 = cuddDynamicAllocNode(table);
13025  if (newf1 == NULL)
13026  goto cuddLinearOutOfMem;
13027  newf1->index = yindex; newf1->ref = 1;
13028  cuddT(newf1) = f11;
13029  cuddE(newf1) = f00;
13030  /* Insert newf1 in the collision list ylist[posn];
13031  ** increase the ref counts of f11 and f00.
13032  */
13033  newykeys++;
13034  newf1->next = *previousP;
13035  *previousP = newf1;
13036  cuddSatInc(f11->ref);
13037  tmp = Cudd_Regular(f00);
13038  cuddSatInc(tmp->ref);
13039  }
13040  }
13041  cuddT(f) = newf1;
13042 #ifdef DD_DEBUG
13043  assert(!(Cudd_IsComplement(newf1)));
13044 #endif
13045 
13046  /* Do the same for f0, keeping complement dots into account. */
13047  /* decrease ref count of f0 */
13048  tmp = Cudd_Regular(f0);
13049  cuddSatDec(tmp->ref);
13050  /* create the new E child */
13051  if (f01 == f10) {
13052  newf0 = f01;
13053  tmp = Cudd_Regular(newf0);
13054  cuddSatInc(tmp->ref);
13055  } else {
13056  /* make sure f01 is regular */
13057  newcomplement = Cudd_IsComplement(f01);
13058  if (newcomplement) {
13059  f01 = Cudd_Not(f01);
13060  f10 = Cudd_Not(f10);
13061  }
13062  /* Check ylist for triple (yindex,f01,f10). */
13063  posn = ddHash(f01, f10, yshift);
13064  /* For each element newf0 in collision list ylist[posn]. */
13065  previousP = &(ylist[posn]);
13066  newf0 = *previousP;
13067  while (f01 < cuddT(newf0)) {
13068  previousP = &(newf0->next);
13069  newf0 = *previousP;
13070  }
13071  while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
13072  previousP = &(newf0->next);
13073  newf0 = *previousP;
13074  }
13075  if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
13076  cuddSatInc(newf0->ref);
13077  } else { /* no match */
13078  newf0 = cuddDynamicAllocNode(table);
13079  if (newf0 == NULL)
13080  goto cuddLinearOutOfMem;
13081  newf0->index = yindex; newf0->ref = 1;
13082  cuddT(newf0) = f01;
13083  cuddE(newf0) = f10;
13084  /* Insert newf0 in the collision list ylist[posn];
13085  ** increase the ref counts of f01 and f10.
13086  */
13087  newykeys++;
13088  newf0->next = *previousP;
13089  *previousP = newf0;
13090  cuddSatInc(f01->ref);
13091  tmp = Cudd_Regular(f10);
13092  cuddSatInc(tmp->ref);
13093  }
13094  if (newcomplement) {
13095  newf0 = Cudd_Not(newf0);
13096  }
13097  }
13098  cuddE(f) = newf0;
13099 
13100  /* Re-insert the modified f in xlist.
13101  ** The modified f does not already exists in xlist.
13102  ** (Because of the uniqueness of the cofactors.)
13103  */
13104  posn = ddHash(newf1, newf0, xshift);
13105  newxkeys++;
13106  previousP = &(xlist[posn]);
13107  tmp = *previousP;
13108  while (newf1 < cuddT(tmp)) {
13109  previousP = &(tmp->next);
13110  tmp = *previousP;
13111  }
13112  while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
13113  previousP = &(tmp->next);
13114  tmp = *previousP;
13115  }
13116  f->next = *previousP;
13117  *previousP = f;
13118  f = next;
13119  } /* while f != NULL */
13120 
13121  /* GC the y layer. */
13122 
13123  /* For each node f in ylist. */
13124  for (i = 0; i < yslots; i++) {
13125  previousP = &(ylist[i]);
13126  f = *previousP;
13127  while (f != sentinel) {
13128  next = f->next;
13129  if (f->ref == 0) {
13130  tmp = cuddT(f);
13131  cuddSatDec(tmp->ref);
13132  tmp = Cudd_Regular(cuddE(f));
13133  cuddSatDec(tmp->ref);
13134  cuddDeallocNode(table,f);
13135  newykeys--;
13136  } else {
13137  *previousP = f;
13138  previousP = &(f->next);
13139  }
13140  f = next;
13141  } /* while f */
13142  *previousP = sentinel;
13143  } /* for every collision list */
13144 
13145 #ifdef DD_DEBUG
13146  #if 0
13147  (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
13148 #endif
13149  count = 0;
13150  idcheck = 0;
13151  for (i = 0; i < yslots; i++) {
13152  f = ylist[i];
13153  while (f != sentinel) {
13154  count++;
13155  if (f->index != (DdHalfWord) yindex)
13156  idcheck++;
13157  f = f->next;
13158  }
13159  }
13160  if (count != newykeys) {
13161  fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
13162  }
13163  if (idcheck != 0)
13164  fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
13165  count = 0;
13166  idcheck = 0;
13167  for (i = 0; i < xslots; i++) {
13168  f = xlist[i];
13169  while (f != sentinel) {
13170  count++;
13171  if (f->index != (DdHalfWord) xindex)
13172  idcheck++;
13173  f = f->next;
13174  }
13175  }
13176  if (count != newxkeys || newxkeys != oldxkeys) {
13177  fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
13178  }
13179  if (idcheck != 0)
13180  fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
13181 #endif
13182 
13183  isolated += (table->vars[xindex]->ref == 1) +
13184  (table->vars[yindex]->ref == 1);
13185  table->isolated += isolated;
13186 
13187  /* Set the appropriate fields in table. */
13188  table->subtables[y].keys = newykeys;
13189 
13190  /* Here we should update the linear combination table
13191  ** to record that x <- x EXNOR y. This is done by complementing
13192  ** the (x,y) entry of the table.
13193  */
13194 
13195  table->keys += newykeys - oldykeys;
13196 
13197  cuddXorLinear(table,xindex,yindex);
13198  }
13199 
13200 #ifdef DD_DEBUG
13201  if (zero) {
13202  (void) Cudd_DebugCheck(table);
13203  }
13204 #endif
13205 
13206  return(table->keys - table->isolated);
13207 
13208  cuddLinearOutOfMem:
13209  (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
13210 
13211  return (0);
13212 
13213 } /* end of cuddLinearInPlace */
13214 
13215 
13227 void
13229  DdManager * table,
13230  int xindex,
13231  int yindex)
13232 {
13233  int i;
13234  for (i = 0; i < yindex; i++) {
13235  if (i != xindex && cuddTestInteract(table,i,yindex)) {
13236  if (i < xindex) {
13237  cuddSetInteract(table,i,xindex);
13238  } else {
13239  cuddSetInteract(table,xindex,i);
13240  }
13241  }
13242  }
13243  for (i = yindex+1; i < table->size; i++) {
13244  if (i != xindex && cuddTestInteract(table,yindex,i)) {
13245  if (i < xindex) {
13246  cuddSetInteract(table,i,xindex);
13247  } else {
13248  cuddSetInteract(table,xindex,i);
13249  }
13250  }
13251  }
13252 
13253 } /* end of cuddUpdateInteractionMatrix */
13254 
13255 
13268 int
13270  DdManager * table)
13271 {
13272  int words;
13273  int wordsPerRow;
13274  int nvars;
13275  int word;
13276  int bit;
13277  int i;
13278  long *linear;
13279 
13280  nvars = table->size;
13281  wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
13282  words = wordsPerRow * nvars;
13283  table->linear = linear = ALLOC(long,words);
13284  if (linear == NULL) {
13285  table->errorCode = CUDD_MEMORY_OUT;
13286  return(0);
13287  }
13288  table->memused += words * sizeof(long);
13289  table->linearSize = nvars;
13290  for (i = 0; i < words; i++) linear[i] = 0;
13291  for (i = 0; i < nvars; i++) {
13292  word = wordsPerRow * i + (i >> LOGBPL);
13293  bit = i & (BPL-1);
13294  linear[word] = 1 << bit;
13295  }
13296  return(1);
13297 
13298 } /* end of cuddInitLinear */
13299 
13300 
13313 int
13315  DdManager * table)
13316 {
13317  int words,oldWords;
13318  int wordsPerRow,oldWordsPerRow;
13319  int nvars,oldNvars;
13320  int word,oldWord;
13321  int bit;
13322  int i,j;
13323  long *linear,*oldLinear;
13324 
13325  oldNvars = table->linearSize;
13326  oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
13327  oldWords = oldWordsPerRow * oldNvars;
13328  oldLinear = table->linear;
13329 
13330  nvars = table->size;
13331  wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
13332  words = wordsPerRow * nvars;
13333  table->linear = linear = ALLOC(long,words);
13334  if (linear == NULL) {
13335  table->errorCode = CUDD_MEMORY_OUT;
13336  return(0);
13337  }
13338  table->memused += (words - oldWords) * sizeof(long);
13339  for (i = 0; i < words; i++) linear[i] = 0;
13340 
13341  /* Copy old matrix. */
13342  for (i = 0; i < oldNvars; i++) {
13343  for (j = 0; j < oldWordsPerRow; j++) {
13344  oldWord = oldWordsPerRow * i + j;
13345  word = wordsPerRow * i + j;
13346  linear[word] = oldLinear[oldWord];
13347  }
13348  }
13349  FREE(oldLinear);
13350 
13351  /* Add elements to the diagonal. */
13352  for (i = oldNvars; i < nvars; i++) {
13353  word = wordsPerRow * i + (i >> LOGBPL);
13354  bit = i & (BPL-1);
13355  linear[word] = 1 << bit;
13356  }
13357  table->linearSize = nvars;
13358 
13359  return(1);
13360 
13361 } /* end of cuddResizeLinear */
13362 
13363 
13364 /*---------------------------------------------------------------------------*/
13365 /* Definition of static functions */
13366 /*---------------------------------------------------------------------------*/
13367 
13368 
13381 static int
13383  int * ptrX,
13384  int * ptrY)
13385 {
13386 #if 0
13387  if (entry[*ptrY] == entry[*ptrX]) {
13388  return((*ptrX) - (*ptrY));
13389  }
13390 #endif
13391  return(entry[*ptrY] - entry[*ptrX]);
13392 
13393 } /* end of ddLinearUniqueCompare */
13394 
13395 
13409 static int
13411  DdManager * table,
13412  int x,
13413  int xLow,
13414  int xHigh)
13415 {
13416 
13417  Move *move;
13418  Move *moveUp; /* list of up moves */
13419  Move *moveDown; /* list of down moves */
13420  int initialSize;
13421  int result;
13422 
13423  initialSize = table->keys - table->isolated;
13424 
13425  moveDown = NULL;
13426  moveUp = NULL;
13427 
13428  if (x == xLow) {
13429  moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
13430  /* At this point x --> xHigh unless bounding occurred. */
13431  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
13432  /* Move backward and stop at best position. */
13433  result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
13434  if (!result) goto ddLinearAndSiftingAuxOutOfMem;
13435 
13436  } else if (x == xHigh) {
13437  moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
13438  /* At this point x --> xLow unless bounding occurred. */
13439  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
13440  /* Move backward and stop at best position. */
13441  result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
13442  if (!result) goto ddLinearAndSiftingAuxOutOfMem;
13443 
13444  } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
13445  moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
13446  /* At this point x --> xHigh unless bounding occurred. */
13447  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
13448  moveUp = ddUndoMoves(table,moveDown);
13449 #ifdef DD_DEBUG
13450  assert(moveUp == NULL || moveUp->x == x);
13451 #endif
13452  moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
13453  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
13454  /* Move backward and stop at best position. */
13455  result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
13456  if (!result) goto ddLinearAndSiftingAuxOutOfMem;
13457 
13458  } else { /* must go up first: shorter */
13459  moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
13460  /* At this point x --> xLow unless bounding occurred. */
13461  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
13462  moveDown = ddUndoMoves(table,moveUp);
13463 #ifdef DD_DEBUG
13464  assert(moveDown == NULL || moveDown->y == x);
13465 #endif
13466  moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
13467  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
13468  /* Move backward and stop at best position. */
13469  result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
13470  if (!result) goto ddLinearAndSiftingAuxOutOfMem;
13471  }
13472 
13473  while (moveDown != NULL) {
13474  move = moveDown->next;
13475  cuddDeallocMove(table, moveDown);
13476  moveDown = move;
13477  }
13478  while (moveUp != NULL) {
13479  move = moveUp->next;
13480  cuddDeallocMove(table, moveUp);
13481  moveUp = move;
13482  }
13483 
13484  return(1);
13485 
13486  ddLinearAndSiftingAuxOutOfMem:
13487  while (moveDown != NULL) {
13488  move = moveDown->next;
13489  cuddDeallocMove(table, moveDown);
13490  moveDown = move;
13491  }
13492  while (moveUp != NULL) {
13493  move = moveUp->next;
13494  cuddDeallocMove(table, moveUp);
13495  moveUp = move;
13496  }
13497 
13498  return(0);
13499 
13500 } /* end of ddLinearAndSiftingAux */
13501 
13502 
13515 static Move *
13517  DdManager * table,
13518  int y,
13519  int xLow,
13520  Move * prevMoves)
13521 {
13522  Move *moves;
13523  Move *move;
13524  int x;
13525  int size, newsize;
13526  int limitSize;
13527  int xindex, yindex;
13528  int isolated;
13529  int L; /* lower bound on DD size */
13530 #ifdef DD_DEBUG
13531  int checkL;
13532  int z;
13533  int zindex;
13534 #endif
13535 
13536  moves = prevMoves;
13537  yindex = table->invperm[y];
13538 
13539  /* Initialize the lower bound.
13540  ** The part of the DD below y will not change.
13541  ** The part of the DD above y that does not interact with y will not
13542  ** change. The rest may vanish in the best case, except for
13543  ** the nodes at level xLow, which will not vanish, regardless.
13544  */
13545  limitSize = L = table->keys - table->isolated;
13546  for (x = xLow + 1; x < y; x++) {
13547  xindex = table->invperm[x];
13548  if (cuddTestInteract(table,xindex,yindex)) {
13549  isolated = table->vars[xindex]->ref == 1;
13550  L -= table->subtables[x].keys - isolated;
13551  }
13552  }
13553  isolated = table->vars[yindex]->ref == 1;
13554  L -= table->subtables[y].keys - isolated;
13555 
13556  x = cuddNextLow(table,y);
13557  while (x >= xLow && L <= limitSize) {
13558  xindex = table->invperm[x];
13559 #ifdef DD_DEBUG
13560  checkL = table->keys - table->isolated;
13561  for (z = xLow + 1; z < y; z++) {
13562  zindex = table->invperm[z];
13563  if (cuddTestInteract(table,zindex,yindex)) {
13564  isolated = table->vars[zindex]->ref == 1;
13565  checkL -= table->subtables[z].keys - isolated;
13566  }
13567  }
13568  isolated = table->vars[yindex]->ref == 1;
13569  checkL -= table->subtables[y].keys - isolated;
13570  if (L != checkL) {
13571  (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
13572  }
13573 #endif
13574  size = cuddSwapInPlace(table,x,y);
13575  if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
13576  newsize = cuddLinearInPlace(table,x,y);
13577  if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
13578  move = (Move *) cuddDynamicAllocNode(table);
13579  if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
13580  move->x = x;
13581  move->y = y;
13582  move->next = moves;
13583  moves = move;
13584  move->flags = CUDD_SWAP_MOVE;
13585  if (newsize >= size) {
13586  /* Undo transformation. The transformation we apply is
13587  ** its own inverse. Hence, we just apply the transformation
13588  ** again.
13589  */
13590  newsize = cuddLinearInPlace(table,x,y);
13591  if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
13592 #ifdef DD_DEBUG
13593  if (newsize != size) {
13594  (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
13595  }
13596 #endif
13597  } else if (cuddTestInteract(table,xindex,yindex)) {
13598  size = newsize;
13600  cuddUpdateInteractionMatrix(table,xindex,yindex);
13601  }
13602  move->size = size;
13603  /* Update the lower bound. */
13604  if (cuddTestInteract(table,xindex,yindex)) {
13605  isolated = table->vars[xindex]->ref == 1;
13606  L += table->subtables[y].keys - isolated;
13607  }
13608  if ((double) size > (double) limitSize * table->maxGrowth) break;
13609  if (size < limitSize) limitSize = size;
13610  y = x;
13611  x = cuddNextLow(table,y);
13612  }
13613  return(moves);
13614 
13615  ddLinearAndSiftingUpOutOfMem:
13616  while (moves != NULL) {
13617  move = moves->next;
13618  cuddDeallocMove(table, moves);
13619  moves = move;
13620  }
13621  return((Move *) CUDD_OUT_OF_MEM);
13622 
13623 } /* end of ddLinearAndSiftingUp */
13624 
13625 
13638 static Move *
13640  DdManager * table,
13641  int x,
13642  int xHigh,
13643  Move * prevMoves)
13644 {
13645  Move *moves;
13646  Move *move;
13647  int y;
13648  int size, newsize;
13649  int R; /* upper bound on node decrease */
13650  int limitSize;
13651  int xindex, yindex;
13652  int isolated;
13653 #ifdef DD_DEBUG
13654  int checkR;
13655  int z;
13656  int zindex;
13657 #endif
13658 
13659  moves = prevMoves;
13660  /* Initialize R */
13661  xindex = table->invperm[x];
13662  limitSize = size = table->keys - table->isolated;
13663  R = 0;
13664  for (y = xHigh; y > x; y--) {
13665  yindex = table->invperm[y];
13666  if (cuddTestInteract(table,xindex,yindex)) {
13667  isolated = table->vars[yindex]->ref == 1;
13668  R += table->subtables[y].keys - isolated;
13669  }
13670  }
13671 
13672  y = cuddNextHigh(table,x);
13673  while (y <= xHigh && size - R < limitSize) {
13674 #ifdef DD_DEBUG
13675  checkR = 0;
13676  for (z = xHigh; z > x; z--) {
13677  zindex = table->invperm[z];
13678  if (cuddTestInteract(table,xindex,zindex)) {
13679  isolated = table->vars[zindex]->ref == 1;
13680  checkR += table->subtables[z].keys - isolated;
13681  }
13682  }
13683  if (R != checkR) {
13684  (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
13685  }
13686 #endif
13687  /* Update upper bound on node decrease. */
13688  yindex = table->invperm[y];
13689  if (cuddTestInteract(table,xindex,yindex)) {
13690  isolated = table->vars[yindex]->ref == 1;
13691  R -= table->subtables[y].keys - isolated;
13692  }
13693  size = cuddSwapInPlace(table,x,y);
13694  if (size == 0) goto ddLinearAndSiftingDownOutOfMem;
13695  newsize = cuddLinearInPlace(table,x,y);
13696  if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
13697  move = (Move *) cuddDynamicAllocNode(table);
13698  if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
13699  move->x = x;
13700  move->y = y;
13701  move->next = moves;
13702  moves = move;
13703  move->flags = CUDD_SWAP_MOVE;
13704  if (newsize >= size) {
13705  /* Undo transformation. The transformation we apply is
13706  ** its own inverse. Hence, we just apply the transformation
13707  ** again.
13708  */
13709  newsize = cuddLinearInPlace(table,x,y);
13710  if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
13711  if (newsize != size) {
13712  (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
13713  }
13714  } else if (cuddTestInteract(table,xindex,yindex)) {
13715  size = newsize;
13717  cuddUpdateInteractionMatrix(table,xindex,yindex);
13718  }
13719  move->size = size;
13720  if ((double) size > (double) limitSize * table->maxGrowth) break;
13721  if (size < limitSize) limitSize = size;
13722  x = y;
13723  y = cuddNextHigh(table,x);
13724  }
13725  return(moves);
13726 
13727  ddLinearAndSiftingDownOutOfMem:
13728  while (moves != NULL) {
13729  move = moves->next;
13730  cuddDeallocMove(table, moves);
13731  moves = move;
13732  }
13733  return((Move *) CUDD_OUT_OF_MEM);
13734 
13735 } /* end of ddLinearAndSiftingDown */
13736 
13737 
13751 static int
13753  DdManager * table,
13754  int size,
13755  Move * moves)
13756 {
13757  Move *move;
13758  int res;
13759 
13760  for (move = moves; move != NULL; move = move->next) {
13761  if (move->size < size) {
13762  size = move->size;
13763  }
13764  }
13765 
13766  for (move = moves; move != NULL; move = move->next) {
13767  if (move->size == size) return(1);
13768  if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
13769  res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
13770  if (!res) return(0);
13771  }
13772  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
13773  if (!res) return(0);
13774  if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
13775  res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
13776  if (!res) return(0);
13777  }
13778  }
13779 
13780  return(1);
13781 
13782 } /* end of ddLinearAndSiftingBackward */
13783 
13784 
13797 static Move*
13799  DdManager * table,
13800  Move * moves)
13801 {
13802  Move *invmoves = NULL;
13803  Move *move;
13804  Move *invmove;
13805  int size;
13806 
13807  for (move = moves; move != NULL; move = move->next) {
13808  invmove = (Move *) cuddDynamicAllocNode(table);
13809  if (invmove == NULL) goto ddUndoMovesOutOfMem;
13810  invmove->x = move->x;
13811  invmove->y = move->y;
13812  invmove->next = invmoves;
13813  invmoves = invmove;
13814  if (move->flags == CUDD_SWAP_MOVE) {
13815  invmove->flags = CUDD_SWAP_MOVE;
13816  size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
13817  if (!size) goto ddUndoMovesOutOfMem;
13818  } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
13820  size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
13821  if (!size) goto ddUndoMovesOutOfMem;
13822  size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
13823  if (!size) goto ddUndoMovesOutOfMem;
13824  } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
13825 #ifdef DD_DEBUG
13826  (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
13827 #endif
13828  invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
13829  size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
13830  if (!size) goto ddUndoMovesOutOfMem;
13831  size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
13832  if (!size) goto ddUndoMovesOutOfMem;
13833  }
13834  invmove->size = size;
13835  }
13836 
13837  return(invmoves);
13838 
13839  ddUndoMovesOutOfMem:
13840  while (invmoves != NULL) {
13841  move = invmoves->next;
13842  cuddDeallocMove(table, invmoves);
13843  invmoves = move;
13844  }
13845  return((Move *) CUDD_OUT_OF_MEM);
13846 
13847 } /* end of ddUndoMoves */
13848 
13849 
13862 static void
13864  DdManager * table,
13865  int x,
13866  int y)
13867 {
13868  int i;
13869  int nvars = table->size;
13870  int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
13871  int xstart = wordsPerRow * x;
13872  int ystart = wordsPerRow * y;
13873  long *linear = table->linear;
13874 
13875  for (i = 0; i < wordsPerRow; i++) {
13876  linear[xstart+i] ^= linear[ystart+i];
13877  }
13878 
13879 } /* end of cuddXorLinear */
13948 /*---------------------------------------------------------------------------*/
13949 /* Constant declarations */
13950 /*---------------------------------------------------------------------------*/
13951 
13952 
13953 /*---------------------------------------------------------------------------*/
13954 /* Stucture declarations */
13955 /*---------------------------------------------------------------------------*/
13956 
13957 
13958 /*---------------------------------------------------------------------------*/
13959 /* Type declarations */
13960 /*---------------------------------------------------------------------------*/
13961 
13962 
13963 /*---------------------------------------------------------------------------*/
13964 /* Variable declarations */
13965 /*---------------------------------------------------------------------------*/
13966 
13967 //#ifndef lint
13968 //static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.29 2012/02/05 01:07:19 fabio Exp $";
13969 //#endif
13970 
13971 /*---------------------------------------------------------------------------*/
13972 /* Macro declarations */
13973 /*---------------------------------------------------------------------------*/
13974 
13975 
13978 /*---------------------------------------------------------------------------*/
13979 /* Static function prototypes */
13980 /*---------------------------------------------------------------------------*/
13981 
13985 /*---------------------------------------------------------------------------*/
13986 /* Definition of exported functions */
13987 /*---------------------------------------------------------------------------*/
13988 
14001 void
14003  DdNode * n)
14004 {
14005 
14006  n = Cudd_Regular(n);
14007 
14008  cuddSatInc(n->ref);
14009 
14010 } /* end of Cudd_Ref */
14011 
14012 
14026 void
14028  DdManager * table,
14029  DdNode * n)
14030 {
14031  DdNode *N;
14032  int ord;
14033  DdNodePtr *stack = table->stack;
14034  int SP = 1;
14035 
14036  unsigned int live = table->keys - table->dead;
14037  if (live > table->peakLiveNodes) {
14038  table->peakLiveNodes = live;
14039  }
14040 
14041  N = Cudd_Regular(n);
14042 
14043  do {
14044 #ifdef DD_DEBUG
14045  assert(N->ref != 0);
14046 #endif
14047 
14048  if (N->ref == 1) {
14049  N->ref = 0;
14050  table->dead++;
14051 #ifdef DD_STATS
14052  table->nodesDropped++;
14053 #endif
14054  if (cuddIsConstant(N)) {
14055  table->constants.dead++;
14056  N = stack[--SP];
14057  } else {
14058  ord = table->perm[N->index];
14059  stack[SP++] = Cudd_Regular(cuddE(N));
14060  table->subtables[ord].dead++;
14061  N = cuddT(N);
14062  }
14063  } else {
14064  cuddSatDec(N->ref);
14065  N = stack[--SP];
14066  }
14067  } while (SP != 0);
14068 
14069 } /* end of Cudd_RecursiveDeref */
14070 
14071 
14089 void
14091  DdManager * table,
14092  DdNode * n)
14093 {
14094  DdNode *N;
14095  int ord;
14096  DdNodePtr *stack = table->stack;
14097  int SP = 1;
14098 
14099  unsigned int live = table->keys - table->dead;
14100  if (live > table->peakLiveNodes) {
14101  table->peakLiveNodes = live;
14102  }
14103 
14104  N = Cudd_Regular(n);
14105 
14106  do {
14107 #ifdef DD_DEBUG
14108  assert(N->ref != 0);
14109 #endif
14110 
14111  if (N->ref == 1) {
14112  N->ref = 0;
14113  table->dead++;
14114 #ifdef DD_STATS
14115  table->nodesDropped++;
14116 #endif
14117  ord = table->perm[N->index];
14118  stack[SP++] = Cudd_Regular(cuddE(N));
14119  table->subtables[ord].dead++;
14120  N = cuddT(N);
14121  } else {
14122  cuddSatDec(N->ref);
14123  N = stack[--SP];
14124  }
14125  } while (SP != 0);
14126 
14127 } /* end of Cudd_IterDerefBdd */
14128 
14129 
14130 
14144 void
14146  DdManager * table,
14147  DdNode * n)
14148 {
14149  DdNode *N;
14150  int ord;
14151  DdNodePtr *stack = table->stack;
14152  int SP = 1;
14153 
14154  N = n;
14155 
14156  do {
14157 #ifdef DD_DEBUG
14158  assert(N->ref != 0);
14159 #endif
14160 
14161  cuddSatDec(N->ref);
14162 
14163  if (N->ref == 0) {
14164  table->deadZ++;
14165 #ifdef DD_STATS
14166  table->nodesDropped++;
14167 #endif
14168 #ifdef DD_DEBUG
14169  assert(!cuddIsConstant(N));
14170 #endif
14171  ord = table->permZ[N->index];
14172  stack[SP++] = cuddE(N);
14173  table->subtableZ[ord].dead++;
14174  N = cuddT(N);
14175  } else {
14176  N = stack[--SP];
14177  }
14178  } while (SP != 0);
14179 
14180 } /* end of Cudd_RecursiveDerefZdd */
14181 
14182 
14197 void
14199  DdNode * node)
14200 {
14201  node = Cudd_Regular(node);
14202  cuddSatDec(node->ref);
14203 
14204 } /* end of Cudd_Deref */
14205 
14206 /*---------------------------------------------------------------------------*/
14207 /* Definition of internal functions */
14208 /*---------------------------------------------------------------------------*/
14209 
14210 
14222 void
14224  DdManager * table,
14225  DdNode * n)
14226 {
14227  DdNode *N;
14228  int ord;
14229  DdNodePtr *stack = table->stack;
14230  int SP = 1;
14231  double initialDead = table->dead;
14232 
14233  N = Cudd_Regular(n);
14234 
14235 #ifdef DD_DEBUG
14236  assert(N->ref == 0);
14237 #endif
14238 
14239  do {
14240  if (N->ref == 0) {
14241  N->ref = 1;
14242  table->dead--;
14243  if (cuddIsConstant(N)) {
14244  table->constants.dead--;
14245  N = stack[--SP];
14246  } else {
14247  ord = table->perm[N->index];
14248  stack[SP++] = Cudd_Regular(cuddE(N));
14249  table->subtables[ord].dead--;
14250  N = cuddT(N);
14251  }
14252  } else {
14253  cuddSatInc(N->ref);
14254  N = stack[--SP];
14255  }
14256  } while (SP != 0);
14257 
14258  N = Cudd_Regular(n);
14259  cuddSatDec(N->ref);
14260  table->reclaimed += initialDead - table->dead;
14261 
14262 } /* end of cuddReclaim */
14263 
14264 
14276 void
14278  DdManager * table,
14279  DdNode * n)
14280 {
14281  DdNode *N;
14282  int ord;
14283  DdNodePtr *stack = table->stack;
14284  int SP = 1;
14285 
14286  N = n;
14287 
14288 #ifdef DD_DEBUG
14289  assert(N->ref == 0);
14290 #endif
14291 
14292  do {
14293  cuddSatInc(N->ref);
14294 
14295  if (N->ref == 1) {
14296  table->deadZ--;
14297  table->reclaimed++;
14298 #ifdef DD_DEBUG
14299  assert(!cuddIsConstant(N));
14300 #endif
14301  ord = table->permZ[N->index];
14302  stack[SP++] = cuddE(N);
14303  table->subtableZ[ord].dead--;
14304  N = cuddT(N);
14305  } else {
14306  N = stack[--SP];
14307  }
14308  } while (SP != 0);
14309 
14310  cuddSatDec(n->ref);
14311 
14312 } /* end of cuddReclaimZdd */
14313 
14314 
14326 void
14328  DdManager *table)
14329 {
14330 #ifndef DD_NO_DEATH_ROW
14331  int i;
14332 
14333  if (table->deathRowDepth > 3) {
14334  for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) {
14335  if (table->deathRow[i] == NULL) break;
14336  Cudd_IterDerefBdd(table,table->deathRow[i]);
14337  table->deathRow[i] = NULL;
14338  }
14339  table->deathRowDepth /= 4;
14340  table->deadMask = table->deathRowDepth - 1;
14341  if ((unsigned) table->nextDead > table->deadMask) {
14342  table->nextDead = 0;
14343  }
14344  table->deathRow = REALLOC(DdNodePtr, table->deathRow,
14345  table->deathRowDepth);
14346  }
14347 #endif
14348 
14349 } /* end of cuddShrinkDeathRow */
14350 
14351 
14364 void
14366  DdManager *table)
14367 {
14368 #ifndef DD_NO_DEATH_ROW
14369  int i;
14370 
14371  for (i = 0; i < table->deathRowDepth; i++) {
14372  if (table->deathRow[i] == NULL) break;
14373  Cudd_IterDerefBdd(table,table->deathRow[i]);
14374  table->deathRow[i] = NULL;
14375  }
14376 #ifdef DD_DEBUG
14377  for (; i < table->deathRowDepth; i++) {
14378  assert(table->deathRow[i] == NULL);
14379  }
14380 #endif
14381  table->nextDead = 0;
14382 #endif
14383 
14384 } /* end of cuddClearDeathRow */
14385 
14386 
14387 /*---------------------------------------------------------------------------*/
14388 /* Definition of static functions */
14389 /*---------------------------------------------------------------------------*/
14465 /*---------------------------------------------------------------------------*/
14466 /* Constant declarations */
14467 /*---------------------------------------------------------------------------*/
14468 
14469 #define DD_MAX_SUBTABLE_SPARSITY 8
14470 
14471 /*---------------------------------------------------------------------------*/
14472 /* Stucture declarations */
14473 /*---------------------------------------------------------------------------*/
14474 
14475 /*---------------------------------------------------------------------------*/
14476 /* Type declarations */
14477 /*---------------------------------------------------------------------------*/
14478 
14479 /*---------------------------------------------------------------------------*/
14480 /* Variable declarations */
14481 /*---------------------------------------------------------------------------*/
14482 
14483 //#ifndef lint
14484 //static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.71 2012/02/05 01:07:19 fabio Exp $";
14485 //#endif
14486 
14487 static int *entry;
14488 
14490 #ifdef DD_STATS
14491 int ddTotalNISwaps;
14492 #endif
14493 
14494 /*---------------------------------------------------------------------------*/
14495 /* Macro declarations */
14496 /*---------------------------------------------------------------------------*/
14497 
14500 /*---------------------------------------------------------------------------*/
14501 /* Static function prototypes */
14502 /*---------------------------------------------------------------------------*/
14503 
14504 static int ddUniqueCompare (int *ptrX, int *ptrY);
14505 static Move * ddSwapAny (DdManager *table, int x, int y);
14506 static int ddSiftingAux (DdManager *table, int x, int xLow, int xHigh);
14507 static Move * ddSiftingUp (DdManager *table, int y, int xLow);
14508 static Move * ddSiftingDown (DdManager *table, int x, int xHigh);
14509 static int ddSiftingBackward (DdManager *table, int size, Move *moves);
14510 static int ddReorderPreprocess (DdManager *table);
14511 static int ddReorderPostprocess (DdManager *table);
14512 static int ddShuffle2 (DdManager *table, int *permutation);
14513 static int ddSiftUp2 (DdManager *table, int x, int xLow);
14514 static void bddFixTree (DdManager *table, MtrNode *treenode);
14515 static int ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
14516 static int ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
14517 
14521 /*---------------------------------------------------------------------------*/
14522 /* Definition of exported functions */
14523 /*---------------------------------------------------------------------------*/
14524 
14525 
14557 int
14559  DdManager * table /* DD manager */,
14560  Cudd_ReorderingType heuristic /* method used for reordering */,
14561  int minsize /* bound below which no reordering occurs */)
14562 {
14563  DdHook *hook;
14564  int result;
14565  unsigned int nextDyn;
14566 #ifdef DD_STATS
14567  unsigned int initialSize;
14568  unsigned int finalSize;
14569 #endif
14570  unsigned long localTime;
14571 
14572  /* Don't reorder if there are too many dead nodes. */
14573  if (table->keys - table->dead < (unsigned) minsize)
14574  return(1);
14575 
14576  if (heuristic == CUDD_REORDER_SAME) {
14577  heuristic = table->autoMethod;
14578  }
14579  if (heuristic == CUDD_REORDER_NONE) {
14580  return(1);
14581  }
14582 
14583  /* This call to Cudd_ReduceHeap does initiate reordering. Therefore
14584  ** we count it.
14585  */
14586  table->reorderings++;
14587 
14588  localTime = util_cpu_time();
14589 
14590  /* Run the hook functions. */
14591  hook = table->preReorderingHook;
14592  while (hook != NULL) {
14593  int res = (hook->f)(table, "BDD", (void *)heuristic);
14594  if (res == 0) return(0);
14595  hook = hook->next;
14596  }
14597 
14598  if (!ddReorderPreprocess(table)) return(0);
14600 
14601  if (table->keys > table->peakLiveNodes) {
14602  table->peakLiveNodes = table->keys;
14603  }
14604 #ifdef DD_STATS
14605  initialSize = table->keys - table->isolated;
14606  ddTotalNISwaps = 0;
14607 
14608  switch(heuristic) {
14609  case CUDD_REORDER_RANDOM:
14611  (void) fprintf(table->out,"#:I_RANDOM ");
14612  break;
14613  case CUDD_REORDER_SIFT:
14619  (void) fprintf(table->out,"#:I_SIFTING ");
14620  break;
14621  case CUDD_REORDER_WINDOW2:
14622  case CUDD_REORDER_WINDOW3:
14623  case CUDD_REORDER_WINDOW4:
14627  (void) fprintf(table->out,"#:I_WINDOW ");
14628  break;
14630  (void) fprintf(table->out,"#:I_ANNEAL ");
14631  break;
14632  case CUDD_REORDER_GENETIC:
14633  (void) fprintf(table->out,"#:I_GENETIC ");
14634  break;
14635  case CUDD_REORDER_LINEAR:
14637  (void) fprintf(table->out,"#:I_LINSIFT ");
14638  break;
14639  case CUDD_REORDER_EXACT:
14640  (void) fprintf(table->out,"#:I_EXACT ");
14641  break;
14642  default:
14643  return(0);
14644  }
14645  (void) fprintf(table->out,"%8d: initial size",initialSize);
14646 #endif
14647 
14648  /* See if we should use alternate threshold for maximum growth. */
14649  if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
14650  double saveGrowth = table->maxGrowth;
14651  table->maxGrowth = table->maxGrowthAlt;
14652  result = cuddTreeSifting(table,heuristic);
14653  table->maxGrowth = saveGrowth;
14654  } else {
14655  result = cuddTreeSifting(table,heuristic);
14656  }
14657 
14658 #ifdef DD_STATS
14659  (void) fprintf(table->out,"\n");
14660  finalSize = table->keys - table->isolated;
14661  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
14662  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
14663  ((double)(util_cpu_time() - localTime)/1000.0));
14664  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
14666  (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
14667 #endif
14668 
14669  if (result == 0)
14670  return(0);
14671 
14672  if (!ddReorderPostprocess(table))
14673  return(0);
14674 
14675  if (table->realign) {
14676  if (!cuddZddAlignToBdd(table))
14677  return(0);
14678  }
14679 
14680  nextDyn = (table->keys - table->constants.keys + 1) *
14681  DD_DYN_RATIO + table->constants.keys;
14682  if (table->reorderings < 20 || nextDyn > table->nextDyn)
14683  table->nextDyn = nextDyn;
14684  else
14685  table->nextDyn += 20;
14686  if (table->randomizeOrder != 0) {
14687  table->nextDyn += Cudd_Random() & table->randomizeOrder;
14688  }
14689  table->reordered = 1;
14690 
14691  /* Run hook functions. */
14692  hook = table->postReorderingHook;
14693  while (hook != NULL) {
14694  int res = (hook->f)(table, "BDD", (void *)localTime);
14695  if (res == 0) return(0);
14696  hook = hook->next;
14697  }
14698  /* Update cumulative reordering time. */
14699  table->reordTime += util_cpu_time() - localTime;
14700 
14701  return(result);
14702 
14703 } /* end of Cudd_ReduceHeap */
14704 
14705 
14706 /*---------------------------------------------------------------------------*/
14707 /* Definition of internal functions */
14708 /*---------------------------------------------------------------------------*/
14709 
14710 
14726 DdNode *
14728  DdManager * table)
14729 {
14730  int i;
14731  DdNodePtr *mem;
14732  DdNode *list, *node;
14733  extern DD_OOMFP MMoutOfMemory;
14734  DD_OOMFP saveHandler;
14735 
14736  if (table->nextFree == NULL) { /* free list is empty */
14737  /* Try to allocate a new block. */
14738  saveHandler = MMoutOfMemory;
14739  MMoutOfMemory = Cudd_OutOfMem;
14740  mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1);
14741  MMoutOfMemory = saveHandler;
14742  if (mem == NULL && table->stash != NULL) {
14743  FREE(table->stash);
14744  table->stash = NULL;
14745  /* Inhibit resizing of tables. */
14746  table->maxCacheHard = table->cacheSlots - 1;
14747  table->cacheSlack = - (int) (table->cacheSlots + 1);
14748  for (i = 0; i < table->size; i++) {
14749  table->subtables[i].maxKeys <<= 2;
14750  }
14751  mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
14752  }
14753  if (mem == NULL) {
14754  /* Out of luck. Call the default handler to do
14755  ** whatever it specifies for a failed malloc. If this
14756  ** handler returns, then set error code, print
14757  ** warning, and return. */
14758  (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
14759  table->errorCode = CUDD_MEMORY_OUT;
14760 #ifdef DD_VERBOSE
14761  (void) fprintf(table->err,
14762  "cuddDynamicAllocNode: out of memory");
14763  (void) fprintf(table->err,"Memory in use = %lu\n",
14764  table->memused);
14765 #endif
14766  return(NULL);
14767  } else { /* successful allocation; slice memory */
14768  unsigned long offset;
14769  table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
14770  mem[0] = (DdNode *) table->memoryList;
14771  table->memoryList = mem;
14772 
14773  /* Here we rely on the fact that the size of a DdNode is a
14774  ** power of 2 and a multiple of the size of a pointer.
14775  ** If we align one node, all the others will be aligned
14776  ** as well. */
14777  offset = (unsigned long) mem & (sizeof(DdNode) - 1);
14778  mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
14779 #ifdef DD_DEBUG
14780  assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
14781 #endif
14782  list = (DdNode *) mem;
14783 
14784  i = 1;
14785  do {
14786  list[i - 1].ref = 0;
14787  list[i - 1].next = &list[i];
14788  } while (++i < DD_MEM_CHUNK);
14789 
14790  list[DD_MEM_CHUNK-1].ref = 0;
14791  list[DD_MEM_CHUNK - 1].next = NULL;
14792 
14793  table->nextFree = &list[0];
14794  }
14795  } /* if free list empty */
14796 
14797  node = table->nextFree;
14798  table->nextFree = node->next;
14799  return (node);
14800 
14801 } /* end of cuddDynamicAllocNode */
14802 
14803 
14823 int
14825  DdManager * table,
14826  int lower,
14827  int upper)
14828 {
14829  int i;
14830  int *var;
14831  int size;
14832  int x;
14833  int result;
14834 #ifdef DD_STATS
14835  int previousSize;
14836 #endif
14837 
14838  size = table->size;
14839 
14840  /* Find order in which to sift variables. */
14841  var = NULL;
14842  entry = ALLOC(int,size);
14843  if (entry == NULL) {
14844  table->errorCode = CUDD_MEMORY_OUT;
14845  goto cuddSiftingOutOfMem;
14846  }
14847  var = ALLOC(int,size);
14848  if (var == NULL) {
14849  table->errorCode = CUDD_MEMORY_OUT;
14850  goto cuddSiftingOutOfMem;
14851  }
14852 
14853  for (i = 0; i < size; i++) {
14854  x = table->perm[i];
14855  entry[i] = table->subtables[x].keys;
14856  var[i] = i;
14857  }
14858 
14859  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
14860 
14861  /* Now sift. */
14862  for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
14863  if (ddTotalNumberSwapping >= table->siftMaxSwap)
14864  break;
14865  if (util_cpu_time() - table->startTime + table->reordTime
14866  > table->timeLimit) {
14867  table->autoDyn = 0; /* prevent further reordering */
14868  break;
14869  }
14870  x = table->perm[var[i]];
14871 
14872  if (x < lower || x > upper || table->subtables[x].bindVar == 1)
14873  continue;
14874 #ifdef DD_STATS
14875  previousSize = table->keys - table->isolated;
14876 #endif
14877  result = ddSiftingAux(table, x, lower, upper);
14878  if (!result) goto cuddSiftingOutOfMem;
14879 #ifdef DD_STATS
14880  if (table->keys < (unsigned) previousSize + table->isolated) {
14881  (void) fprintf(table->out,"-");
14882  } else if (table->keys > (unsigned) previousSize + table->isolated) {
14883  (void) fprintf(table->out,"+"); /* should never happen */
14884  (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
14885  } else {
14886  (void) fprintf(table->out,"=");
14887  }
14888  fflush(table->out);
14889 #endif
14890  }
14891 
14892  FREE(var);
14893  FREE(entry);
14894 
14895  return(1);
14896 
14897  cuddSiftingOutOfMem:
14898 
14899  if (entry != NULL) FREE(entry);
14900  if (var != NULL) FREE(var);
14901 
14902  return(0);
14903 
14904 } /* end of cuddSifting */
14905 
14906 
14925 int
14927  DdManager * table,
14928  int lower,
14929  int upper,
14930  Cudd_ReorderingType heuristic)
14931 {
14932  int i, j;
14933  int max, keys;
14934  int nvars;
14935  int x, y;
14936  int iterate;
14937  int previousSize;
14938  Move *moves, *move;
14939  int pivot;
14940  int modulo;
14941  int result;
14942 
14943 #ifdef DD_DEBUG
14944  /* Sanity check */
14945  assert(lower >= 0 && upper < table->size && lower <= upper);
14946 #endif
14947 
14948  nvars = upper - lower + 1;
14949  iterate = nvars;
14950 
14951  for (i = 0; i < iterate; i++) {
14952  if (ddTotalNumberSwapping >= table->siftMaxSwap)
14953  break;
14954  if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
14955  max = -1;
14956  for (j = lower; j <= upper; j++) {
14957  if ((keys = table->subtables[j].keys) > max) {
14958  max = keys;
14959  pivot = j;
14960  }
14961  }
14962 
14963  modulo = upper - pivot;
14964  if (modulo == 0) {
14965  y = pivot;
14966  } else{
14967  y = pivot + 1 + ((int) Cudd_Random() % modulo);
14968  }
14969 
14970  modulo = pivot - lower - 1;
14971  if (modulo < 1) {
14972  x = lower;
14973  } else{
14974  do {
14975  x = (int) Cudd_Random() % modulo;
14976  } while (x == y);
14977  }
14978  } else {
14979  x = ((int) Cudd_Random() % nvars) + lower;
14980  do {
14981  y = ((int) Cudd_Random() % nvars) + lower;
14982  } while (x == y);
14983  }
14984  previousSize = table->keys - table->isolated;
14985  moves = ddSwapAny(table,x,y);
14986  if (moves == NULL) goto cuddSwappingOutOfMem;
14987  result = ddSiftingBackward(table,previousSize,moves);
14988  if (!result) goto cuddSwappingOutOfMem;
14989  while (moves != NULL) {
14990  move = moves->next;
14991  cuddDeallocMove(table, moves);
14992  moves = move;
14993  }
14994 #ifdef DD_STATS
14995  if (table->keys < (unsigned) previousSize + table->isolated) {
14996  (void) fprintf(table->out,"-");
14997  } else if (table->keys > (unsigned) previousSize + table->isolated) {
14998  (void) fprintf(table->out,"+"); /* should never happen */
14999  } else {
15000  (void) fprintf(table->out,"=");
15001  }
15002  fflush(table->out);
15003 #endif
15004 #if 0
15005  (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
15006  table->keys - table->isolated);
15007 #endif
15008  }
15009 
15010  return(1);
15011 
15012  cuddSwappingOutOfMem:
15013  while (moves != NULL) {
15014  move = moves->next;
15015  cuddDeallocMove(table, moves);
15016  moves = move;
15017  }
15018 
15019  return(0);
15020 
15021 } /* end of cuddSwapping */
15022 
15023 
15036 int
15038  DdManager * table,
15039  int x)
15040 {
15041  return(x+1);
15042 
15043 } /* end of cuddNextHigh */
15044 
15045 
15058 int
15060  DdManager * table,
15061  int x)
15062 {
15063  return(x-1);
15064 
15065 } /* end of cuddNextLow */
15066 
15067 
15081 int
15083  DdManager * table,
15084  int x,
15085  int y)
15086 {
15087  DdNodePtr *xlist, *ylist;
15088  int xindex, yindex;
15089  int xslots, yslots;
15090  int xshift, yshift;
15091  int oldxkeys, oldykeys;
15092  int newxkeys, newykeys;
15093  int comple, newcomplement;
15094  int i;
15095  Cudd_VariableType varType;
15096  Cudd_LazyGroupType groupType;
15097  int posn;
15098  int isolated;
15099  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
15100  DdNode *g,*next;
15101  DdNodePtr *previousP;
15102  DdNode *tmp;
15103  DdNode *sentinel = &(table->sentinel);
15104  extern DD_OOMFP MMoutOfMemory;
15105  DD_OOMFP saveHandler;
15106 
15107 #ifdef DD_DEBUG
15108  int count,idcheck;
15109 #endif
15110 
15111 #ifdef DD_DEBUG
15112  assert(x < y);
15113  assert(cuddNextHigh(table,x) == y);
15114  assert(table->subtables[x].keys != 0);
15115  assert(table->subtables[y].keys != 0);
15116  assert(table->subtables[x].dead == 0);
15117  assert(table->subtables[y].dead == 0);
15118 #endif
15119 
15121 
15122  /* Get parameters of x subtable. */
15123  xindex = table->invperm[x];
15124  xlist = table->subtables[x].nodelist;
15125  oldxkeys = table->subtables[x].keys;
15126  xslots = table->subtables[x].slots;
15127  xshift = table->subtables[x].shift;
15128 
15129  /* Get parameters of y subtable. */
15130  yindex = table->invperm[y];
15131  ylist = table->subtables[y].nodelist;
15132  oldykeys = table->subtables[y].keys;
15133  yslots = table->subtables[y].slots;
15134  yshift = table->subtables[y].shift;
15135 
15136  if (!cuddTestInteract(table,xindex,yindex)) {
15137 #ifdef DD_STATS
15138  ddTotalNISwaps++;
15139 #endif
15140  newxkeys = oldxkeys;
15141  newykeys = oldykeys;
15142  } else {
15143  newxkeys = 0;
15144  newykeys = oldykeys;
15145 
15146  /* Check whether the two projection functions involved in this
15147  ** swap are isolated. At the end, we'll be able to tell how many
15148  ** isolated projection functions are there by checking only these
15149  ** two functions again. This is done to eliminate the isolated
15150  ** projection functions from the node count.
15151  */
15152  isolated = - ((table->vars[xindex]->ref == 1) +
15153  (table->vars[yindex]->ref == 1));
15154 
15155  /* The nodes in the x layer that do not depend on
15156  ** y will stay there; the others are put in a chain.
15157  ** The chain is handled as a LIFO; g points to the beginning.
15158  */
15159  g = NULL;
15160  if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
15161  oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
15162  for (i = 0; i < xslots; i++) {
15163  previousP = &(xlist[i]);
15164  f = *previousP;
15165  while (f != sentinel) {
15166  next = f->next;
15167  f1 = cuddT(f); f0 = cuddE(f);
15168  if (f1->index != (DdHalfWord) yindex &&
15169  Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
15170  /* stays */
15171  newxkeys++;
15172  *previousP = f;
15173  previousP = &(f->next);
15174  } else {
15175  f->index = yindex;
15176  f->next = g;
15177  g = f;
15178  }
15179  f = next;
15180  } /* while there are elements in the collision chain */
15181  *previousP = sentinel;
15182  } /* for each slot of the x subtable */
15183  } else { /* resize xlist */
15184  DdNode *h = NULL;
15185  DdNodePtr *newxlist;
15186  unsigned int newxslots;
15187  int newxshift;
15188  /* Empty current xlist. Nodes that stay go to list h;
15189  ** nodes that move go to list g. */
15190  for (i = 0; i < xslots; i++) {
15191  f = xlist[i];
15192  while (f != sentinel) {
15193  next = f->next;
15194  f1 = cuddT(f); f0 = cuddE(f);
15195  if (f1->index != (DdHalfWord) yindex &&
15196  Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
15197  /* stays */
15198  f->next = h;
15199  h = f;
15200  newxkeys++;
15201  } else {
15202  f->index = yindex;
15203  f->next = g;
15204  g = f;
15205  }
15206  f = next;
15207  } /* while there are elements in the collision chain */
15208  } /* for each slot of the x subtable */
15209  /* Decide size of new subtable. */
15210  newxshift = xshift;
15211  newxslots = xslots;
15212  while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) {
15213  newxshift--;
15214  newxslots <<= 1;
15215  }
15216  while ((unsigned) oldxkeys < newxslots &&
15217  newxslots > table->initSlots) {
15218  newxshift++;
15219  newxslots >>= 1;
15220  }
15221  /* Try to allocate new table. Be ready to back off. */
15222  saveHandler = MMoutOfMemory;
15223  MMoutOfMemory = Cudd_OutOfMem;
15224  newxlist = ALLOC(DdNodePtr, newxslots);
15225  MMoutOfMemory = saveHandler;
15226  if (newxlist == NULL) {
15227  (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
15228  newxlist = xlist;
15229  newxslots = xslots;
15230  newxshift = xshift;
15231  } else {
15232  table->slots += ((int) newxslots - xslots);
15233  table->minDead = (unsigned)
15234  (table->gcFrac * (double) table->slots);
15235  table->cacheSlack = (int)
15237  * table->slots) - 2 * (int) table->cacheSlots;
15238  table->memused +=
15239  ((int) newxslots - xslots) * sizeof(DdNodePtr);
15240  FREE(xlist);
15241  xslots = newxslots;
15242  xshift = newxshift;
15243  xlist = newxlist;
15244  }
15245  /* Initialize new subtable. */
15246  for (i = 0; i < xslots; i++) {
15247  xlist[i] = sentinel;
15248  }
15249  /* Move nodes that were parked in list h to their new home. */
15250  f = h;
15251  while (f != NULL) {
15252  next = f->next;
15253  f1 = cuddT(f);
15254  f0 = cuddE(f);
15255  /* Check xlist for pair (f11,f01). */
15256  posn = ddHash(f1, f0, xshift);
15257  /* For each element tmp in collision list xlist[posn]. */
15258  previousP = &(xlist[posn]);
15259  tmp = *previousP;
15260  while (f1 < cuddT(tmp)) {
15261  previousP = &(tmp->next);
15262  tmp = *previousP;
15263  }
15264  while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
15265  previousP = &(tmp->next);
15266  tmp = *previousP;
15267  }
15268  f->next = *previousP;
15269  *previousP = f;
15270  f = next;
15271  }
15272  }
15273 
15274 #ifdef DD_COUNT
15275  table->swapSteps += oldxkeys - newxkeys;
15276 #endif
15277  /* Take care of the x nodes that must be re-expressed.
15278  ** They form a linked list pointed by g. Their index has been
15279  ** already changed to yindex.
15280  */
15281  f = g;
15282  while (f != NULL) {
15283  next = f->next;
15284  /* Find f1, f0, f11, f10, f01, f00. */
15285  f1 = cuddT(f);
15286 #ifdef DD_DEBUG
15287  assert(!(Cudd_IsComplement(f1)));
15288 #endif
15289  if ((int) f1->index == yindex) {
15290  f11 = cuddT(f1); f10 = cuddE(f1);
15291  } else {
15292  f11 = f10 = f1;
15293  }
15294 #ifdef DD_DEBUG
15295  assert(!(Cudd_IsComplement(f11)));
15296 #endif
15297  f0 = cuddE(f);
15298  comple = Cudd_IsComplement(f0);
15299  f0 = Cudd_Regular(f0);
15300  if ((int) f0->index == yindex) {
15301  f01 = cuddT(f0); f00 = cuddE(f0);
15302  } else {
15303  f01 = f00 = f0;
15304  }
15305  if (comple) {
15306  f01 = Cudd_Not(f01);
15307  f00 = Cudd_Not(f00);
15308  }
15309  /* Decrease ref count of f1. */
15310  cuddSatDec(f1->ref);
15311  /* Create the new T child. */
15312  if (f11 == f01) {
15313  newf1 = f11;
15314  cuddSatInc(newf1->ref);
15315  } else {
15316  /* Check xlist for triple (xindex,f11,f01). */
15317  posn = ddHash(f11, f01, xshift);
15318  /* For each element newf1 in collision list xlist[posn]. */
15319  previousP = &(xlist[posn]);
15320  newf1 = *previousP;
15321  while (f11 < cuddT(newf1)) {
15322  previousP = &(newf1->next);
15323  newf1 = *previousP;
15324  }
15325  while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
15326  previousP = &(newf1->next);
15327  newf1 = *previousP;
15328  }
15329  if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
15330  cuddSatInc(newf1->ref);
15331  } else { /* no match */
15332  newf1 = cuddDynamicAllocNode(table);
15333  if (newf1 == NULL)
15334  goto cuddSwapOutOfMem;
15335  newf1->index = xindex; newf1->ref = 1;
15336  cuddT(newf1) = f11;
15337  cuddE(newf1) = f01;
15338  /* Insert newf1 in the collision list xlist[posn];
15339  ** increase the ref counts of f11 and f01.
15340  */
15341  newxkeys++;
15342  newf1->next = *previousP;
15343  *previousP = newf1;
15344  cuddSatInc(f11->ref);
15345  tmp = Cudd_Regular(f01);
15346  cuddSatInc(tmp->ref);
15347  }
15348  }
15349  cuddT(f) = newf1;
15350 #ifdef DD_DEBUG
15351  assert(!(Cudd_IsComplement(newf1)));
15352 #endif
15353 
15354  /* Do the same for f0, keeping complement dots into account. */
15355  /* Decrease ref count of f0. */
15356  tmp = Cudd_Regular(f0);
15357  cuddSatDec(tmp->ref);
15358  /* Create the new E child. */
15359  if (f10 == f00) {
15360  newf0 = f00;
15361  tmp = Cudd_Regular(newf0);
15362  cuddSatInc(tmp->ref);
15363  } else {
15364  /* make sure f10 is regular */
15365  newcomplement = Cudd_IsComplement(f10);
15366  if (newcomplement) {
15367  f10 = Cudd_Not(f10);
15368  f00 = Cudd_Not(f00);
15369  }
15370  /* Check xlist for triple (xindex,f10,f00). */
15371  posn = ddHash(f10, f00, xshift);
15372  /* For each element newf0 in collision list xlist[posn]. */
15373  previousP = &(xlist[posn]);
15374  newf0 = *previousP;
15375  while (f10 < cuddT(newf0)) {
15376  previousP = &(newf0->next);
15377  newf0 = *previousP;
15378  }
15379  while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
15380  previousP = &(newf0->next);
15381  newf0 = *previousP;
15382  }
15383  if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
15384  cuddSatInc(newf0->ref);
15385  } else { /* no match */
15386  newf0 = cuddDynamicAllocNode(table);
15387  if (newf0 == NULL)
15388  goto cuddSwapOutOfMem;
15389  newf0->index = xindex; newf0->ref = 1;
15390  cuddT(newf0) = f10;
15391  cuddE(newf0) = f00;
15392  /* Insert newf0 in the collision list xlist[posn];
15393  ** increase the ref counts of f10 and f00.
15394  */
15395  newxkeys++;
15396  newf0->next = *previousP;
15397  *previousP = newf0;
15398  cuddSatInc(f10->ref);
15399  tmp = Cudd_Regular(f00);
15400  cuddSatInc(tmp->ref);
15401  }
15402  if (newcomplement) {
15403  newf0 = Cudd_Not(newf0);
15404  }
15405  }
15406  cuddE(f) = newf0;
15407 
15408  /* Insert the modified f in ylist.
15409  ** The modified f does not already exists in ylist.
15410  ** (Because of the uniqueness of the cofactors.)
15411  */
15412  posn = ddHash(newf1, newf0, yshift);
15413  newykeys++;
15414  previousP = &(ylist[posn]);
15415  tmp = *previousP;
15416  while (newf1 < cuddT(tmp)) {
15417  previousP = &(tmp->next);
15418  tmp = *previousP;
15419  }
15420  while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
15421  previousP = &(tmp->next);
15422  tmp = *previousP;
15423  }
15424  f->next = *previousP;
15425  *previousP = f;
15426  f = next;
15427  } /* while f != NULL */
15428 
15429  /* GC the y layer. */
15430 
15431  /* For each node f in ylist. */
15432  for (i = 0; i < yslots; i++) {
15433  previousP = &(ylist[i]);
15434  f = *previousP;
15435  while (f != sentinel) {
15436  next = f->next;
15437  if (f->ref == 0) {
15438  tmp = cuddT(f);
15439  cuddSatDec(tmp->ref);
15440  tmp = Cudd_Regular(cuddE(f));
15441  cuddSatDec(tmp->ref);
15442  cuddDeallocNode(table,f);
15443  newykeys--;
15444  } else {
15445  *previousP = f;
15446  previousP = &(f->next);
15447  }
15448  f = next;
15449  } /* while f */
15450  *previousP = sentinel;
15451  } /* for i */
15452 
15453 #ifdef DD_DEBUG
15454  #if 0
15455  (void) fprintf(table->out,"Swapping %d and %d\n",x,y);
15456 #endif
15457  count = 0;
15458  idcheck = 0;
15459  for (i = 0; i < yslots; i++) {
15460  f = ylist[i];
15461  while (f != sentinel) {
15462  count++;
15463  if (f->index != (DdHalfWord) yindex)
15464  idcheck++;
15465  f = f->next;
15466  }
15467  }
15468  if (count != newykeys) {
15469  (void) fprintf(table->out,
15470  "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
15471  oldykeys,newykeys,count);
15472  }
15473  if (idcheck != 0)
15474  (void) fprintf(table->out,
15475  "Error in id's of ylist\twrong id's = %d\n",
15476  idcheck);
15477  count = 0;
15478  idcheck = 0;
15479  for (i = 0; i < xslots; i++) {
15480  f = xlist[i];
15481  while (f != sentinel) {
15482  count++;
15483  if (f->index != (DdHalfWord) xindex)
15484  idcheck++;
15485  f = f->next;
15486  }
15487  }
15488  if (count != newxkeys) {
15489  (void) fprintf(table->out,
15490  "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
15491  oldxkeys,newxkeys,count);
15492  }
15493  if (idcheck != 0)
15494  (void) fprintf(table->out,
15495  "Error in id's of xlist\twrong id's = %d\n",
15496  idcheck);
15497 #endif
15498 
15499  isolated += (table->vars[xindex]->ref == 1) +
15500  (table->vars[yindex]->ref == 1);
15501  table->isolated += isolated;
15502  }
15503 
15504  /* Set the appropriate fields in table. */
15505  table->subtables[x].nodelist = ylist;
15506  table->subtables[x].slots = yslots;
15507  table->subtables[x].shift = yshift;
15508  table->subtables[x].keys = newykeys;
15509  table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
15510  i = table->subtables[x].bindVar;
15511  table->subtables[x].bindVar = table->subtables[y].bindVar;
15512  table->subtables[y].bindVar = i;
15513  /* Adjust filds for lazy sifting. */
15514  varType = table->subtables[x].varType;
15515  table->subtables[x].varType = table->subtables[y].varType;
15516  table->subtables[y].varType = varType;
15517  i = table->subtables[x].pairIndex;
15518  table->subtables[x].pairIndex = table->subtables[y].pairIndex;
15519  table->subtables[y].pairIndex = i;
15520  i = table->subtables[x].varHandled;
15521  table->subtables[x].varHandled = table->subtables[y].varHandled;
15522  table->subtables[y].varHandled = i;
15523  groupType = table->subtables[x].varToBeGrouped;
15524  table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
15525  table->subtables[y].varToBeGrouped = groupType;
15526 
15527  table->subtables[y].nodelist = xlist;
15528  table->subtables[y].slots = xslots;
15529  table->subtables[y].shift = xshift;
15530  table->subtables[y].keys = newxkeys;
15531  table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
15532 
15533  table->perm[xindex] = y; table->perm[yindex] = x;
15534  table->invperm[x] = yindex; table->invperm[y] = xindex;
15535 
15536  table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
15537 
15538  return(table->keys - table->isolated);
15539 
15540  cuddSwapOutOfMem:
15541  (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
15542 
15543  return (0);
15544 
15545 } /* end of cuddSwapInPlace */
15546 
15547 
15571 int
15573  DdManager * table /* DD manager */)
15574 {
15575  int *invperm; /* permutation array */
15576  int M; /* ratio of ZDD variables to BDD variables */
15577  int i; /* loop index */
15578  int result; /* return value */
15579 
15580  /* We assume that a ratio of 0 is OK. */
15581  if (table->size == 0)
15582  return(1);
15583 
15584  M = table->sizeZ / table->size;
15585  /* Check whether the number of ZDD variables is a multiple of the
15586  ** number of BDD variables.
15587  */
15588  if (M * table->size != table->sizeZ)
15589  return(0);
15590  /* Create and initialize the inverse permutation array. */
15591  invperm = ALLOC(int,table->size);
15592  if (invperm == NULL) {
15593  table->errorCode = CUDD_MEMORY_OUT;
15594  return(0);
15595  }
15596  for (i = 0; i < table->sizeZ; i += M) {
15597  int indexZ = table->invpermZ[i];
15598  int index = indexZ / M;
15599  invperm[i / M] = index;
15600  }
15601  /* Eliminate dead nodes. Do not scan the cache again, because we
15602  ** assume that Cudd_zddReduceHeap has already cleared it.
15603  */
15604  cuddGarbageCollect(table,0);
15605 
15606  /* Initialize number of isolated projection functions. */
15607  table->isolated = 0;
15608  for (i = 0; i < table->size; i++) {
15609  if (table->vars[i]->ref == 1) table->isolated++;
15610  }
15611 
15612  /* Initialize the interaction matrix. */
15613  result = cuddInitInteract(table);
15614  if (result == 0) return(0);
15615 
15616  result = ddShuffle2(table, invperm);
15617  FREE(invperm);
15618  /* Free interaction matrix. */
15619  FREE(table->interact);
15620  /* Fix the BDD variable group tree. */
15621  bddFixTree(table,table->tree);
15622  return(result);
15623 
15624 } /* end of cuddBddAlignToZdd */
15625 
15626 /*---------------------------------------------------------------------------*/
15627 /* Definition of static functions */
15628 /*---------------------------------------------------------------------------*/
15629 
15630 
15643 static int
15645  int * ptrX,
15646  int * ptrY)
15647 {
15648 #if 0
15649  if (entry[*ptrY] == entry[*ptrX]) {
15650  return((*ptrX) - (*ptrY));
15651  }
15652 #endif
15653  return(entry[*ptrY] - entry[*ptrX]);
15654 
15655 } /* end of ddUniqueCompare */
15656 
15657 
15667 static Move *
15669  DdManager * table,
15670  int x,
15671  int y)
15672 {
15673  Move *move, *moves;
15674  int xRef,yRef;
15675  int xNext,yNext;
15676  int size;
15677  int limitSize;
15678  int tmp;
15679 
15680  if (x >y) {
15681  tmp = x; x = y; y = tmp;
15682  }
15683 
15684  xRef = x; yRef = y;
15685 
15686  xNext = cuddNextHigh(table,x);
15687  yNext = cuddNextLow(table,y);
15688  moves = NULL;
15689  limitSize = table->keys - table->isolated;
15690 
15691  for (;;) {
15692  if ( xNext == yNext) {
15693  size = cuddSwapInPlace(table,x,xNext);
15694  if (size == 0) goto ddSwapAnyOutOfMem;
15695  move = (Move *) cuddDynamicAllocNode(table);
15696  if (move == NULL) goto ddSwapAnyOutOfMem;
15697  move->x = x;
15698  move->y = xNext;
15699  move->size = size;
15700  move->next = moves;
15701  moves = move;
15702 
15703  size = cuddSwapInPlace(table,yNext,y);
15704  if (size == 0) goto ddSwapAnyOutOfMem;
15705  move = (Move *) cuddDynamicAllocNode(table);
15706  if (move == NULL) goto ddSwapAnyOutOfMem;
15707  move->x = yNext;
15708  move->y = y;
15709  move->size = size;
15710  move->next = moves;
15711  moves = move;
15712 
15713  size = cuddSwapInPlace(table,x,xNext);
15714  if (size == 0) goto ddSwapAnyOutOfMem;
15715  move = (Move *) cuddDynamicAllocNode(table);
15716  if (move == NULL) goto ddSwapAnyOutOfMem;
15717  move->x = x;
15718  move->y = xNext;
15719  move->size = size;
15720  move->next = moves;
15721  moves = move;
15722 
15723  tmp = x; x = y; y = tmp;
15724 
15725  } else if (x == yNext) {
15726 
15727  size = cuddSwapInPlace(table,x,xNext);
15728  if (size == 0) goto ddSwapAnyOutOfMem;
15729  move = (Move *) cuddDynamicAllocNode(table);
15730  if (move == NULL) goto ddSwapAnyOutOfMem;
15731  move->x = x;
15732  move->y = xNext;
15733  move->size = size;
15734  move->next = moves;
15735  moves = move;
15736 
15737  tmp = x; x = y; y = tmp;
15738 
15739  } else {
15740  size = cuddSwapInPlace(table,x,xNext);
15741  if (size == 0) goto ddSwapAnyOutOfMem;
15742  move = (Move *) cuddDynamicAllocNode(table);
15743  if (move == NULL) goto ddSwapAnyOutOfMem;
15744  move->x = x;
15745  move->y = xNext;
15746  move->size = size;
15747  move->next = moves;
15748  moves = move;
15749 
15750  size = cuddSwapInPlace(table,yNext,y);
15751  if (size == 0) goto ddSwapAnyOutOfMem;
15752  move = (Move *) cuddDynamicAllocNode(table);
15753  if (move == NULL) goto ddSwapAnyOutOfMem;
15754  move->x = yNext;
15755  move->y = y;
15756  move->size = size;
15757  move->next = moves;
15758  moves = move;
15759 
15760  x = xNext;
15761  y = yNext;
15762  }
15763 
15764  xNext = cuddNextHigh(table,x);
15765  yNext = cuddNextLow(table,y);
15766  if (xNext > yRef) break;
15767 
15768  if ((double) size > table->maxGrowth * (double) limitSize) break;
15769  if (size < limitSize) limitSize = size;
15770  }
15771  if (yNext>=xRef) {
15772  size = cuddSwapInPlace(table,yNext,y);
15773  if (size == 0) goto ddSwapAnyOutOfMem;
15774  move = (Move *) cuddDynamicAllocNode(table);
15775  if (move == NULL) goto ddSwapAnyOutOfMem;
15776  move->x = yNext;
15777  move->y = y;
15778  move->size = size;
15779  move->next = moves;
15780  moves = move;
15781  }
15782 
15783  return(moves);
15784 
15785  ddSwapAnyOutOfMem:
15786  while (moves != NULL) {
15787  move = moves->next;
15788  cuddDeallocMove(table, moves);
15789  moves = move;
15790  }
15791  return(NULL);
15792 
15793 } /* end of ddSwapAny */
15794 
15795 
15808 static int
15810  DdManager * table,
15811  int x,
15812  int xLow,
15813  int xHigh)
15814 {
15815 
15816  Move *move;
15817  Move *moveUp; /* list of up moves */
15818  Move *moveDown; /* list of down moves */
15819  int initialSize;
15820  int result;
15821 
15822  initialSize = table->keys - table->isolated;
15823 
15824  moveDown = NULL;
15825  moveUp = NULL;
15826 
15827  if (x == xLow) {
15828  moveDown = ddSiftingDown(table,x,xHigh);
15829  /* At this point x --> xHigh unless bounding occurred. */
15830  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
15831  /* Move backward and stop at best position. */
15832  result = ddSiftingBackward(table,initialSize,moveDown);
15833  if (!result) goto ddSiftingAuxOutOfMem;
15834 
15835  } else if (x == xHigh) {
15836  moveUp = ddSiftingUp(table,x,xLow);
15837  /* At this point x --> xLow unless bounding occurred. */
15838  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
15839  /* Move backward and stop at best position. */
15840  result = ddSiftingBackward(table,initialSize,moveUp);
15841  if (!result) goto ddSiftingAuxOutOfMem;
15842 
15843  } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
15844  moveDown = ddSiftingDown(table,x,xHigh);
15845  /* At this point x --> xHigh unless bounding occurred. */
15846  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
15847  if (moveDown != NULL) {
15848  x = moveDown->y;
15849  }
15850  moveUp = ddSiftingUp(table,x,xLow);
15851  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
15852  /* Move backward and stop at best position */
15853  result = ddSiftingBackward(table,initialSize,moveUp);
15854  if (!result) goto ddSiftingAuxOutOfMem;
15855 
15856  } else { /* must go up first: shorter */
15857  moveUp = ddSiftingUp(table,x,xLow);
15858  /* At this point x --> xLow unless bounding occurred. */
15859  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
15860  if (moveUp != NULL) {
15861  x = moveUp->x;
15862  }
15863  moveDown = ddSiftingDown(table,x,xHigh);
15864  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
15865  /* Move backward and stop at best position. */
15866  result = ddSiftingBackward(table,initialSize,moveDown);
15867  if (!result) goto ddSiftingAuxOutOfMem;
15868  }
15869 
15870  while (moveDown != NULL) {
15871  move = moveDown->next;
15872  cuddDeallocMove(table, moveDown);
15873  moveDown = move;
15874  }
15875  while (moveUp != NULL) {
15876  move = moveUp->next;
15877  cuddDeallocMove(table, moveUp);
15878  moveUp = move;
15879  }
15880 
15881  return(1);
15882 
15883  ddSiftingAuxOutOfMem:
15884  if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
15885  while (moveDown != NULL) {
15886  move = moveDown->next;
15887  cuddDeallocMove(table, moveDown);
15888  moveDown = move;
15889  }
15890  }
15891  if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
15892  while (moveUp != NULL) {
15893  move = moveUp->next;
15894  cuddDeallocMove(table, moveUp);
15895  moveUp = move;
15896  }
15897  }
15898 
15899  return(0);
15900 
15901 } /* end of ddSiftingAux */
15902 
15903 
15915 static Move *
15917  DdManager * table,
15918  int y,
15919  int xLow)
15920 {
15921  Move *moves;
15922  Move *move;
15923  int x;
15924  int size;
15925  int limitSize;
15926  int xindex, yindex;
15927  int isolated;
15928  int L; /* lower bound on DD size */
15929 #ifdef DD_DEBUG
15930  int checkL;
15931  int z;
15932  int zindex;
15933 #endif
15934 
15935  moves = NULL;
15936  yindex = table->invperm[y];
15937 
15938  /* Initialize the lower bound.
15939  ** The part of the DD below y will not change.
15940  ** The part of the DD above y that does not interact with y will not
15941  ** change. The rest may vanish in the best case, except for
15942  ** the nodes at level xLow, which will not vanish, regardless.
15943  */
15944  limitSize = L = table->keys - table->isolated;
15945  for (x = xLow + 1; x < y; x++) {
15946  xindex = table->invperm[x];
15947  if (cuddTestInteract(table,xindex,yindex)) {
15948  isolated = table->vars[xindex]->ref == 1;
15949  L -= table->subtables[x].keys - isolated;
15950  }
15951  }
15952  isolated = table->vars[yindex]->ref == 1;
15953  L -= table->subtables[y].keys - isolated;
15954 
15955  x = cuddNextLow(table,y);
15956  while (x >= xLow && L <= limitSize) {
15957  xindex = table->invperm[x];
15958 #ifdef DD_DEBUG
15959  checkL = table->keys - table->isolated;
15960  for (z = xLow + 1; z < y; z++) {
15961  zindex = table->invperm[z];
15962  if (cuddTestInteract(table,zindex,yindex)) {
15963  isolated = table->vars[zindex]->ref == 1;
15964  checkL -= table->subtables[z].keys - isolated;
15965  }
15966  }
15967  isolated = table->vars[yindex]->ref == 1;
15968  checkL -= table->subtables[y].keys - isolated;
15969  assert(L == checkL);
15970 #endif
15971  size = cuddSwapInPlace(table,x,y);
15972  if (size == 0) goto ddSiftingUpOutOfMem;
15973  /* Update the lower bound. */
15974  if (cuddTestInteract(table,xindex,yindex)) {
15975  isolated = table->vars[xindex]->ref == 1;
15976  L += table->subtables[y].keys - isolated;
15977  }
15978  move = (Move *) cuddDynamicAllocNode(table);
15979  if (move == NULL) goto ddSiftingUpOutOfMem;
15980  move->x = x;
15981  move->y = y;
15982  move->size = size;
15983  move->next = moves;
15984  moves = move;
15985  if ((double) size > (double) limitSize * table->maxGrowth) break;
15986  if (size < limitSize) limitSize = size;
15987  y = x;
15988  x = cuddNextLow(table,y);
15989  }
15990  return(moves);
15991 
15992  ddSiftingUpOutOfMem:
15993  while (moves != NULL) {
15994  move = moves->next;
15995  cuddDeallocMove(table, moves);
15996  moves = move;
15997  }
15998  return((Move *) CUDD_OUT_OF_MEM);
15999 
16000 } /* end of ddSiftingUp */
16001 
16002 
16015 static Move *
16017  DdManager * table,
16018  int x,
16019  int xHigh)
16020 {
16021  Move *moves;
16022  Move *move;
16023  int y;
16024  int size;
16025  int R; /* upper bound on node decrease */
16026  int limitSize;
16027  int xindex, yindex;
16028  int isolated;
16029 #ifdef DD_DEBUG
16030  int checkR;
16031  int z;
16032  int zindex;
16033 #endif
16034 
16035  moves = NULL;
16036  /* Initialize R */
16037  xindex = table->invperm[x];
16038  limitSize = size = table->keys - table->isolated;
16039  R = 0;
16040  for (y = xHigh; y > x; y--) {
16041  yindex = table->invperm[y];
16042  if (cuddTestInteract(table,xindex,yindex)) {
16043  isolated = table->vars[yindex]->ref == 1;
16044  R += table->subtables[y].keys - isolated;
16045  }
16046  }
16047 
16048  y = cuddNextHigh(table,x);
16049  while (y <= xHigh && size - R < limitSize) {
16050 #ifdef DD_DEBUG
16051  checkR = 0;
16052  for (z = xHigh; z > x; z--) {
16053  zindex = table->invperm[z];
16054  if (cuddTestInteract(table,xindex,zindex)) {
16055  isolated = table->vars[zindex]->ref == 1;
16056  checkR += table->subtables[z].keys - isolated;
16057  }
16058  }
16059  assert(R == checkR);
16060 #endif
16061  /* Update upper bound on node decrease. */
16062  yindex = table->invperm[y];
16063  if (cuddTestInteract(table,xindex,yindex)) {
16064  isolated = table->vars[yindex]->ref == 1;
16065  R -= table->subtables[y].keys - isolated;
16066  }
16067  size = cuddSwapInPlace(table,x,y);
16068  if (size == 0) goto ddSiftingDownOutOfMem;
16069  move = (Move *) cuddDynamicAllocNode(table);
16070  if (move == NULL) goto ddSiftingDownOutOfMem;
16071  move->x = x;
16072  move->y = y;
16073  move->size = size;
16074  move->next = moves;
16075  moves = move;
16076  if ((double) size > (double) limitSize * table->maxGrowth) break;
16077  if (size < limitSize) limitSize = size;
16078  x = y;
16079  y = cuddNextHigh(table,x);
16080  }
16081  return(moves);
16082 
16083  ddSiftingDownOutOfMem:
16084  while (moves != NULL) {
16085  move = moves->next;
16086  cuddDeallocMove(table, moves);
16087  moves = move;
16088  }
16089  return((Move *) CUDD_OUT_OF_MEM);
16090 
16091 } /* end of ddSiftingDown */
16092 
16093 
16107 static int
16109  DdManager * table,
16110  int size,
16111  Move * moves)
16112 {
16113  Move *move;
16114  int res;
16115 
16116  for (move = moves; move != NULL; move = move->next) {
16117  if (move->size < size) {
16118  size = move->size;
16119  }
16120  }
16121 
16122  for (move = moves; move != NULL; move = move->next) {
16123  if (move->size == size) return(1);
16124  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
16125  if (!res) return(0);
16126  }
16127 
16128  return(1);
16129 
16130 } /* end of ddSiftingBackward */
16131 
16132 
16146 static int
16148  DdManager * table)
16149 {
16150  int i;
16151  int res;
16152 
16153  /* Clear the cache. */
16154  cuddCacheFlush(table);
16155  cuddLocalCacheClearAll(table);
16156 
16157  /* Eliminate dead nodes. Do not scan the cache again. */
16158  cuddGarbageCollect(table,0);
16159 
16160  /* Initialize number of isolated projection functions. */
16161  table->isolated = 0;
16162  for (i = 0; i < table->size; i++) {
16163  if (table->vars[i]->ref == 1) table->isolated++;
16164  }
16165 
16166  /* Initialize the interaction matrix. */
16167  res = cuddInitInteract(table);
16168  if (res == 0) return(0);
16169 
16170  return(1);
16171 
16172 } /* end of ddReorderPreprocess */
16173 
16174 
16184 static int
16186  DdManager * table)
16187 {
16188 
16189 #ifdef DD_VERBOSE
16190  (void) fflush(table->out);
16191 #endif
16192 
16193  /* Free interaction matrix. */
16194  FREE(table->interact);
16195 
16196  return(1);
16197 
16198 } /* end of ddReorderPostprocess */
16199 
16200 
16217 static int
16219  DdManager * table,
16220  int * permutation)
16221 {
16222  int index;
16223  int level;
16224  int position;
16225  int numvars;
16226  int result;
16227 #ifdef DD_STATS
16228  unsigned long localTime;
16229  int initialSize;
16230  int finalSize;
16231  int previousSize;
16232 #endif
16233 
16235 #ifdef DD_STATS
16236  localTime = util_cpu_time();
16237  initialSize = table->keys - table->isolated;
16238  (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
16239  initialSize);
16240  ddTotalNISwaps = 0;
16241 #endif
16242 
16243  numvars = table->size;
16244 
16245  for (level = 0; level < numvars; level++) {
16246  index = permutation[level];
16247  position = table->perm[index];
16248 #ifdef DD_STATS
16249  previousSize = table->keys - table->isolated;
16250 #endif
16251  result = ddSiftUp2(table,position,level);
16252  if (!result) return(0);
16253 #ifdef DD_STATS
16254  if (table->keys < (unsigned) previousSize + table->isolated) {
16255  (void) fprintf(table->out,"-");
16256  } else if (table->keys > (unsigned) previousSize + table->isolated) {
16257  (void) fprintf(table->out,"+"); /* should never happen */
16258  } else {
16259  (void) fprintf(table->out,"=");
16260  }
16261  fflush(table->out);
16262 #endif
16263  }
16264 
16265 #ifdef DD_STATS
16266  (void) fprintf(table->out,"\n");
16267  finalSize = table->keys - table->isolated;
16268  (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
16269  (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
16270  ((double)(util_cpu_time() - localTime)/1000.0));
16271  (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
16273  (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps);
16274 #endif
16275 
16276  return(1);
16277 
16278 } /* end of ddShuffle */
16279 
16280 
16294 static int
16296  DdManager * table,
16297  int x,
16298  int xLow)
16299 {
16300  int y;
16301  int size;
16302 
16303  y = cuddNextLow(table,x);
16304  while (y >= xLow) {
16305  size = cuddSwapInPlace(table,y,x);
16306  if (size == 0) {
16307  return(0);
16308  }
16309  x = y;
16310  y = cuddNextLow(table,x);
16311  }
16312  return(1);
16313 
16314 } /* end of ddSiftUp */
16315 
16316 
16330 static void
16332  DdManager * table,
16333  MtrNode * treenode)
16334 {
16335  if (treenode == NULL) return;
16336  treenode->low = ((int) treenode->index < table->size) ?
16337  table->perm[treenode->index] : treenode->index;
16338  if (treenode->child != NULL) {
16339  bddFixTree(table, treenode->child);
16340  }
16341  if (treenode->younger != NULL)
16342  bddFixTree(table, treenode->younger);
16343  if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
16344  treenode->parent->low = treenode->low;
16345  treenode->parent->index = treenode->index;
16346  }
16347  return;
16348 
16349 } /* end of bddFixTree */
16350 
16351 
16364 static int
16366  DdManager * table,
16367  MtrNode * treenode,
16368  int * perm,
16369  int * invperm)
16370 {
16371  unsigned int i, size;
16372  int index, level, minLevel, maxLevel, minIndex;
16373 
16374  if (treenode == NULL) return(1);
16375 
16376  minLevel = CUDD_MAXINDEX;
16377  maxLevel = 0;
16378  minIndex = -1;
16379  /* i : level */
16380  for (i = treenode->low; i < treenode->low + treenode->size; i++) {
16381  index = table->invperm[i];
16382  level = perm[index];
16383  if (level < minLevel) {
16384  minLevel = level;
16385  minIndex = index;
16386  }
16387  if (level > maxLevel)
16388  maxLevel = level;
16389  }
16390  size = maxLevel - minLevel + 1;
16391  if (minIndex == -1) return(0);
16392  if (size == treenode->size) {
16393  treenode->low = minLevel;
16394  treenode->index = minIndex;
16395  } else {
16396  return(0);
16397  }
16398 
16399  if (treenode->child != NULL) {
16400  if (!ddUpdateMtrTree(table, treenode->child, perm, invperm))
16401  return(0);
16402  }
16403  if (treenode->younger != NULL) {
16404  if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm))
16405  return(0);
16406  }
16407  return(1);
16408 }
16409 
16410 
16423 static int
16425  DdManager * table,
16426  MtrNode * treenode,
16427  int * perm,
16428  int * invperm)
16429 {
16430  unsigned int i, size;
16431  int index, level, minLevel, maxLevel;
16432 
16433  if (treenode == NULL) return(1);
16434 
16435  minLevel = table->size;
16436  maxLevel = 0;
16437  /* i : level */
16438  for (i = treenode->low; i < treenode->low + treenode->size; i++) {
16439  index = table->invperm[i];
16440  level = perm[index];
16441  if (level < minLevel)
16442  minLevel = level;
16443  if (level > maxLevel)
16444  maxLevel = level;
16445  }
16446  size = maxLevel - minLevel + 1;
16447  if (size != treenode->size)
16448  return(0);
16449 
16450  if (treenode->child != NULL) {
16451  if (!ddCheckPermuation(table, treenode->child, perm, invperm))
16452  return(0);
16453  }
16454  if (treenode->younger != NULL) {
16455  if (!ddCheckPermuation(table, treenode->younger, perm, invperm))
16456  return(0);
16457  }
16458  return(1);
16459 }
16535 /*---------------------------------------------------------------------------*/
16536 /* Constant declarations */
16537 /*---------------------------------------------------------------------------*/
16538 
16539 #define DD_BIGGY 100000000
16540 
16541 /*---------------------------------------------------------------------------*/
16542 /* Stucture declarations */
16543 /*---------------------------------------------------------------------------*/
16544 
16545 /*---------------------------------------------------------------------------*/
16546 /* Type declarations */
16547 /*---------------------------------------------------------------------------*/
16548 
16549  typedef struct cuddPathPair {
16550  int pos;
16551  int neg;
16552  } cuddPathPair;
16553 
16554 /*---------------------------------------------------------------------------*/
16555 /* Variable declarations */
16556 /*---------------------------------------------------------------------------*/
16557 
16558 //#ifndef lint
16559 //static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.39 2012/02/05 01:07:19 fabio Exp $";
16560 //#endif
16561 
16562  static DdNode *one, *zero;
16563 
16564 /*---------------------------------------------------------------------------*/
16565 /* Macro declarations */
16566 /*---------------------------------------------------------------------------*/
16567 
16568 #define WEIGHT(weight, col) ((weight) == NULL ? 1 : weight[col])
16569 
16570 #ifdef __cplusplus
16571  extern "C" {
16572 #endif
16573 
16576 /*---------------------------------------------------------------------------*/
16577 /* Static function prototypes */
16578 /*---------------------------------------------------------------------------*/
16579 
16580  static enum st_retval freePathPair (char *key, char *value, char *arg);
16581  static cuddPathPair getShortest (DdNode *root, int *cost, int *support, st_table *visited);
16582 
16583  static cuddPathPair getLargest (DdNode *root, st_table *visited);
16584  static DdNode * getCube (DdManager *manager, st_table *visited, DdNode *f, int cost);
16585  static DdNode * ddBddMaximallyExpand(DdManager *dd, DdNode *lb, DdNode *ub, DdNode *f);
16586  static int ddBddShortestPathUnate(DdManager *dd, DdNode *f, int *phases, st_table *table);
16587 
16590 #ifdef __cplusplus
16591  }
16592 #endif
16593 
16594 /*---------------------------------------------------------------------------*/
16595 /* Definition of exported functions */
16596 /*---------------------------------------------------------------------------*/
16597 
16615  DdNode *
16617  DdManager * manager,
16618  DdNode * f,
16619  int * length)
16620  {
16621  register DdNode *F;
16622  st_table *visited;
16623  DdNode *sol;
16624  cuddPathPair *rootPair;
16625  int complement, cost;
16626 
16627  one = DD_ONE(manager);
16628  zero = DD_ZERO(manager);
16629 
16630  if (f == Cudd_Not(one) || f == zero) {
16631  if (length != NULL) {
16632  *length = DD_BIGGY;
16633  }
16634  return(Cudd_Not(one));
16635  }
16636  /* From this point on, a path exists. */
16637 
16638  do {
16639  manager->reordered = 0;
16640 
16641  /* Initialize visited table. */
16642  visited = st_init_table(st_ptrcmp, st_ptrhash);
16643 
16644  /* Now get the length of the shortest path(s) from f to 1. */
16645  (void) getLargest(f, visited);
16646 
16647  complement = Cudd_IsComplement(f);
16648 
16649  F = Cudd_Regular(f);
16650 
16651  if (!st_lookup(visited, F, &rootPair)) return(NULL);
16652 
16653  if (complement) {
16654  cost = rootPair->neg;
16655  } else {
16656  cost = rootPair->pos;
16657  }
16658 
16659  /* Recover an actual shortest path. */
16660  sol = getCube(manager,visited,f,cost);
16661 
16662  st_foreach(visited, freePathPair, NULL);
16663  st_free_table(visited);
16664 
16665  } while (manager->reordered == 1);
16666 
16667  if (length != NULL) {
16668  *length = cost;
16669  }
16670  return(sol);
16671 
16672  } /* end of Cudd_LargestCube */
16673 
16674 
16690  DdNode *
16692  DdManager * dd,
16693  DdNode * f,
16694  int i)
16695  {
16696  unsigned int topf, level;
16697  DdNode *F, *fv, *fvn, *res;
16698  DD_CTFP cacheOp;
16699 
16700  statLine(dd);
16701 #ifdef DD_DEBUG
16702  assert(0 <= i && i < dd->size);
16703 #endif
16704 
16705  F = Cudd_Regular(f);
16706  topf = cuddI(dd,F->index);
16707 
16708  /* Check terminal case. If topf > i, f does not depend on var.
16709  ** Therefore, f is unate in i.
16710  */
16711  level = (unsigned) dd->perm[i];
16712  if (topf > level) {
16713  return(DD_ONE(dd));
16714  }
16715 
16716  /* From now on, f is not constant. */
16717 
16718  /* Check cache. */
16719  cacheOp = (DD_CTFP) Cudd_Decreasing;
16720  res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]);
16721  if (res != NULL) {
16722  return(res);
16723  }
16724 
16725  /* Compute cofactors. */
16726  fv = cuddT(F); fvn = cuddE(F);
16727  if (F != f) {
16728  fv = Cudd_Not(fv);
16729  fvn = Cudd_Not(fvn);
16730  }
16731 
16732  if (topf == (unsigned) level) {
16733  /* Special case: if fv is regular, fv(1,...,1) = 1;
16734  ** If in addition fvn is complemented, fvn(1,...,1) = 0.
16735  ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not
16736  ** monotonic decreasing in i.
16737  */
16738  if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) {
16739  return(Cudd_Not(DD_ONE(dd)));
16740  }
16741  res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd));
16742  } else {
16743  res = Cudd_Decreasing(dd,fv,i);
16744  if (res == DD_ONE(dd)) {
16745  res = Cudd_Decreasing(dd,fvn,i);
16746  }
16747  }
16748 
16749  cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res);
16750  return(res);
16751 
16752  } /* end of Cudd_Decreasing */
16753 
16754 
16769  int
16771  DdManager * dd,
16772  DdNode * F,
16773  DdNode * G,
16774  DdNode * D)
16775  {
16776  DdNode *tmp, *One, *Gr, *Dr;
16777  DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn;
16778  int res;
16779  unsigned int flevel, glevel, dlevel, top;
16780 
16781  One = DD_ONE(dd);
16782 
16783  statLine(dd);
16784  /* Check terminal cases. */
16785  if (D == One || F == G) return(1);
16786  if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0);
16787 
16788  /* From now on, D is non-constant. */
16789 
16790  /* Normalize call to increase cache efficiency. */
16791  if (F > G) {
16792  tmp = F;
16793  F = G;
16794  G = tmp;
16795  }
16796  if (Cudd_IsComplement(F)) {
16797  F = Cudd_Not(F);
16798  G = Cudd_Not(G);
16799  }
16800 
16801  /* From now on, F is regular. */
16802 
16803  /* Check cache. */
16804  tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D);
16805  if (tmp != NULL) return(tmp == One);
16806 
16807  /* Find splitting variable. */
16808  flevel = cuddI(dd,F->index);
16809  Gr = Cudd_Regular(G);
16810  glevel = cuddI(dd,Gr->index);
16811  top = ddMin(flevel,glevel);
16812  Dr = Cudd_Regular(D);
16813  dlevel = dd->perm[Dr->index];
16814  top = ddMin(top,dlevel);
16815 
16816  /* Compute cofactors. */
16817  if (top == flevel) {
16818  Fv = cuddT(F);
16819  Fvn = cuddE(F);
16820  } else {
16821  Fv = Fvn = F;
16822  }
16823  if (top == glevel) {
16824  Gv = cuddT(Gr);
16825  Gvn = cuddE(Gr);
16826  if (G != Gr) {
16827  Gv = Cudd_Not(Gv);
16828  Gvn = Cudd_Not(Gvn);
16829  }
16830  } else {
16831  Gv = Gvn = G;
16832  }
16833  if (top == dlevel) {
16834  Dv = cuddT(Dr);
16835  Dvn = cuddE(Dr);
16836  if (D != Dr) {
16837  Dv = Cudd_Not(Dv);
16838  Dvn = Cudd_Not(Dvn);
16839  }
16840  } else {
16841  Dv = Dvn = D;
16842  }
16843 
16844  /* Solve recursively. */
16845  res = Cudd_EquivDC(dd,Fv,Gv,Dv);
16846  if (res != 0) {
16847  res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn);
16848  }
16849  cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One));
16850 
16851  return(res);
16852 
16853  } /* end of Cudd_EquivDC */
16854 
16855 
16869  int
16871  DdManager *dd,
16872  DdNode *f,
16873  DdNode *g,
16874  DdNode *D)
16875  {
16876  DdNode *tmp, *One, *F, *G;
16877  DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De;
16878  int res;
16879  unsigned int flevel, glevel, dlevel, top;
16880 
16881  statLine(dd);
16882 
16883  One = DD_ONE(dd);
16884 
16885  /* Check terminal cases. */
16886  if (f == g || g == One || f == Cudd_Not(One) || D == One ||
16887  D == f || D == Cudd_Not(g)) return(1);
16888  /* Check for two-operand cases. */
16889  if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f))
16890  return(Cudd_bddLeq(dd,f,g));
16891  if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D));
16892  if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D));
16893 
16894  /* From now on, f, g, and D are non-constant, distinct, and
16895  ** non-complementary. */
16896 
16897  /* Normalize call to increase cache efficiency. We rely on the
16898  ** fact that f <= g unless D is equivalent to not(g) <= not(f)
16899  ** unless D and to f <= D unless g. We make sure that D is
16900  ** regular, and that at most one of f and g is complemented. We also
16901  ** ensure that when two operands can be swapped, the one with the
16902  ** lowest address comes first. */
16903 
16904  if (Cudd_IsComplement(D)) {
16905  if (Cudd_IsComplement(g)) {
16906  /* Special case: if f is regular and g is complemented,
16907  ** f(1,...,1) = 1 > 0 = g(1,...,1). If D(1,...,1) = 0, return 0.
16908  */
16909  if (!Cudd_IsComplement(f)) return(0);
16910  /* !g <= D unless !f or !D <= g unless !f */
16911  tmp = D;
16912  D = Cudd_Not(f);
16913  if (g < tmp) {
16914  f = Cudd_Not(g);
16915  g = tmp;
16916  } else {
16917  f = Cudd_Not(tmp);
16918  }
16919  } else {
16920  if (Cudd_IsComplement(f)) {
16921  /* !D <= !f unless g or !D <= g unless !f */
16922  tmp = f;
16923  f = Cudd_Not(D);
16924  if (tmp < g) {
16925  D = g;
16926  g = Cudd_Not(tmp);
16927  } else {
16928  D = Cudd_Not(tmp);
16929  }
16930  } else {
16931  /* f <= D unless g or !D <= !f unless g */
16932  tmp = D;
16933  D = g;
16934  if (tmp < f) {
16935  g = Cudd_Not(f);
16936  f = Cudd_Not(tmp);
16937  } else {
16938  g = tmp;
16939  }
16940  }
16941  }
16942  } else {
16943  if (Cudd_IsComplement(g)) {
16944  if (Cudd_IsComplement(f)) {
16945  /* !g <= !f unless D or !g <= D unless !f */
16946  tmp = f;
16947  f = Cudd_Not(g);
16948  if (D < tmp) {
16949  g = D;
16950  D = Cudd_Not(tmp);
16951  } else {
16952  g = Cudd_Not(tmp);
16953  }
16954  } else {
16955  /* f <= g unless D or !g <= !f unless D */
16956  if (g < f) {
16957  tmp = g;
16958  g = Cudd_Not(f);
16959  f = Cudd_Not(tmp);
16960  }
16961  }
16962  } else {
16963  /* f <= g unless D or f <= D unless g */
16964  if (D < g) {
16965  tmp = D;
16966  D = g;
16967  g = tmp;
16968  }
16969  }
16970  }
16971 
16972  /* From now on, D is regular. */
16973 
16974  /* Check cache. */
16975  tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D);
16976  if (tmp != NULL) return(tmp == One);
16977 
16978  /* Find splitting variable. */
16979  F = Cudd_Regular(f);
16980  flevel = dd->perm[F->index];
16981  G = Cudd_Regular(g);
16982  glevel = dd->perm[G->index];
16983  top = ddMin(flevel,glevel);
16984  dlevel = dd->perm[D->index];
16985  top = ddMin(top,dlevel);
16986 
16987  /* Compute cofactors. */
16988  if (top == flevel) {
16989  Ft = cuddT(F);
16990  Fe = cuddE(F);
16991  if (F != f) {
16992  Ft = Cudd_Not(Ft);
16993  Fe = Cudd_Not(Fe);
16994  }
16995  } else {
16996  Ft = Fe = f;
16997  }
16998  if (top == glevel) {
16999  Gt = cuddT(G);
17000  Ge = cuddE(G);
17001  if (G != g) {
17002  Gt = Cudd_Not(Gt);
17003  Ge = Cudd_Not(Ge);
17004  }
17005  } else {
17006  Gt = Ge = g;
17007  }
17008  if (top == dlevel) {
17009  Dt = cuddT(D);
17010  De = cuddE(D);
17011  } else {
17012  Dt = De = D;
17013  }
17014 
17015  /* Solve recursively. */
17016  res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt);
17017  if (res != 0) {
17018  res = Cudd_bddLeqUnless(dd,Fe,Ge,De);
17019  }
17021 
17022  return(res);
17023 
17024  } /* end of Cudd_bddLeqUnless */
17025 
17026 
17043  int
17045  DdManager * dd /* manager */,
17046  DdNode * f /* first ADD */,
17047  DdNode * g /* second ADD */,
17048  CUDD_VALUE_TYPE tolerance /* maximum allowed difference */,
17049  int pr /* verbosity level */)
17050  {
17051  DdNode *fv, *fvn, *gv, *gvn, *r;
17052  unsigned int topf, topg;
17053 
17054  statLine(dd);
17055  /* Check terminal cases. */
17056  if (f == g) return(1);
17057  if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) {
17058  if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) {
17059  return(1);
17060  } else {
17061  if (pr>0) {
17062  (void) fprintf(dd->out,"Offending nodes:\n");
17063  (void) fprintf(dd->out,
17064  "f: address = %p\t value = %40.30f\n",
17065  (void *) f, cuddV(f));
17066  (void) fprintf(dd->out,
17067  "g: address = %p\t value = %40.30f\n",
17068  (void *) g, cuddV(g));
17069  }
17070  return(0);
17071  }
17072  }
17073 
17074  /* We only insert the result in the cache if the comparison is
17075  ** successful. Therefore, if we hit we return 1. */
17077  if (r != NULL) {
17078  return(1);
17079  }
17080 
17081  /* Compute the cofactors and solve the recursive subproblems. */
17082  topf = cuddI(dd,f->index);
17083  topg = cuddI(dd,g->index);
17084 
17085  if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
17086  if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
17087 
17088  if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0);
17089  if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0);
17090 
17091  cuddCacheInsert2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g,DD_ONE(dd));
17092 
17093  return(1);
17094 
17095  } /* end of Cudd_EqualSupNorm */
17096 
17097 
17111  DdNode *
17113  DdManager *dd /* manager */,
17114  DdNode *cube /* cube to be expanded */,
17115  DdNode *f /* function of which the cube is to be made a prime */)
17116  {
17117  DdNode *res;
17118 
17119  if (!Cudd_bddLeq(dd,cube,f)) return(NULL);
17120 
17121  do {
17122  dd->reordered = 0;
17123  res = cuddBddMakePrime(dd,cube,f);
17124  } while (dd->reordered == 1);
17125  return(res);
17126 
17127  } /* end of Cudd_bddMakePrime */
17128 
17129 
17130 /*---------------------------------------------------------------------------*/
17131 /* Definition of internal functions */
17132 /*---------------------------------------------------------------------------*/
17133 
17134 
17147  DdNode *
17149  DdManager *dd /* manager */,
17150  DdNode *cube /* cube to be expanded */,
17151  DdNode *f /* function of which the cube is to be made a prime */)
17152  {
17153  DdNode *scan;
17154  DdNode *t, *e;
17155  DdNode *res = cube;
17156  DdNode *zero = Cudd_Not(DD_ONE(dd));
17157 
17158  Cudd_Ref(res);
17159  scan = cube;
17160  while (!Cudd_IsConstant(scan)) {
17161  DdNode *reg = Cudd_Regular(scan);
17162  DdNode *var = dd->vars[reg->index];
17163  DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
17164  if (expanded == NULL) {
17165  Cudd_RecursiveDeref(dd,res);
17166  return(NULL);
17167  }
17168  Cudd_Ref(expanded);
17169  if (Cudd_bddLeq(dd,expanded,f)) {
17170  Cudd_RecursiveDeref(dd,res);
17171  res = expanded;
17172  } else {
17173  Cudd_RecursiveDeref(dd,expanded);
17174  }
17175  cuddGetBranches(scan,&t,&e);
17176  if (t == zero) {
17177  scan = e;
17178  } else if (e == zero) {
17179  scan = t;
17180  } else {
17181  Cudd_RecursiveDeref(dd,res);
17182  return(NULL); /* cube is not a cube */
17183  }
17184  }
17185 
17186  if (scan == DD_ONE(dd)) {
17187  Cudd_Deref(res);
17188  return(res);
17189  } else {
17190  Cudd_RecursiveDeref(dd,res);
17191  return(NULL);
17192  }
17193 
17194  } /* end of cuddBddMakePrime */
17195 
17196 
17197 /*---------------------------------------------------------------------------*/
17198 /* Definition of static functions */
17199 /*---------------------------------------------------------------------------*/
17200 
17201 
17212  static enum st_retval
17214  char * key,
17215  char * value,
17216  char * arg)
17217  {
17218  cuddPathPair *pair;
17219 
17220  pair = (cuddPathPair *) value;
17221  FREE(pair);
17222  return(ST_CONTINUE);
17223 
17224  } /* end of freePathPair */
17225 
17226 
17245  static cuddPathPair
17247  DdNode * root,
17248  int * cost,
17249  int * support,
17250  st_table * visited)
17251  {
17252  cuddPathPair *my_pair, res_pair, pair_T, pair_E;
17253  DdNode *my_root, *T, *E;
17254  int weight;
17255 
17256  my_root = Cudd_Regular(root);
17257 
17258  if (st_lookup(visited, my_root, &my_pair)) {
17259  if (Cudd_IsComplement(root)) {
17260  res_pair.pos = my_pair->neg;
17261  res_pair.neg = my_pair->pos;
17262  } else {
17263  res_pair.pos = my_pair->pos;
17264  res_pair.neg = my_pair->neg;
17265  }
17266  return(res_pair);
17267  }
17268 
17269  /* In the case of a BDD the following test is equivalent to
17270  ** testing whether the BDD is the constant 1. This formulation,
17271  ** however, works for ADDs as well, by assuming the usual
17272  ** dichotomy of 0 and != 0.
17273  */
17274  if (cuddIsConstant(my_root)) {
17275  if (my_root != zero) {
17276  res_pair.pos = 0;
17277  res_pair.neg = DD_BIGGY;
17278  } else {
17279  res_pair.pos = DD_BIGGY;
17280  res_pair.neg = 0;
17281  }
17282  } else {
17283  T = cuddT(my_root);
17284  E = cuddE(my_root);
17285 
17286  pair_T = getShortest(T, cost, support, visited);
17287  pair_E = getShortest(E, cost, support, visited);
17288  weight = WEIGHT(cost, my_root->index);
17289  res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos);
17290  res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg);
17291 
17292  /* Update support. */
17293  if (support != NULL) {
17294  support[my_root->index] = 1;
17295  }
17296  }
17297 
17298  my_pair = ALLOC(cuddPathPair, 1);
17299  if (my_pair == NULL) {
17300  if (Cudd_IsComplement(root)) {
17301  int tmp = res_pair.pos;
17302  res_pair.pos = res_pair.neg;
17303  res_pair.neg = tmp;
17304  }
17305  return(res_pair);
17306  }
17307  my_pair->pos = res_pair.pos;
17308  my_pair->neg = res_pair.neg;
17309 
17310  st_insert(visited, (char *)my_root, (char *)my_pair);
17311  if (Cudd_IsComplement(root)) {
17312  res_pair.pos = my_pair->neg;
17313  res_pair.neg = my_pair->pos;
17314  } else {
17315  res_pair.pos = my_pair->pos;
17316  res_pair.neg = my_pair->neg;
17317  }
17318  return(res_pair);
17319 
17320  } /* end of getShortest */
17321 
17322 
17323 /* end of getPath */
17324 
17325 
17346  static cuddPathPair
17348  DdNode * root,
17349  st_table * visited)
17350  {
17351  cuddPathPair *my_pair, res_pair, pair_T, pair_E;
17352  DdNode *my_root, *T, *E;
17353 
17354  my_root = Cudd_Regular(root);
17355 
17356  if (st_lookup(visited, my_root, &my_pair)) {
17357  if (Cudd_IsComplement(root)) {
17358  res_pair.pos = my_pair->neg;
17359  res_pair.neg = my_pair->pos;
17360  } else {
17361  res_pair.pos = my_pair->pos;
17362  res_pair.neg = my_pair->neg;
17363  }
17364  return(res_pair);
17365  }
17366 
17367  /* In the case of a BDD the following test is equivalent to
17368  ** testing whether the BDD is the constant 1. This formulation,
17369  ** however, works for ADDs as well, by assuming the usual
17370  ** dichotomy of 0 and != 0.
17371  */
17372  if (cuddIsConstant(my_root)) {
17373  if (my_root != zero) {
17374  res_pair.pos = 0;
17375  res_pair.neg = DD_BIGGY;
17376  } else {
17377  res_pair.pos = DD_BIGGY;
17378  res_pair.neg = 0;
17379  }
17380  } else {
17381  T = cuddT(my_root);
17382  E = cuddE(my_root);
17383 
17384  pair_T = getLargest(T, visited);
17385  pair_E = getLargest(E, visited);
17386  res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1;
17387  res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1;
17388  }
17389 
17390  my_pair = ALLOC(cuddPathPair, 1);
17391  if (my_pair == NULL) { /* simply do not cache this result */
17392  if (Cudd_IsComplement(root)) {
17393  int tmp = res_pair.pos;
17394  res_pair.pos = res_pair.neg;
17395  res_pair.neg = tmp;
17396  }
17397  return(res_pair);
17398  }
17399  my_pair->pos = res_pair.pos;
17400  my_pair->neg = res_pair.neg;
17401 
17402  /* Caching may fail without affecting correctness. */
17403  st_insert(visited, (char *)my_root, (char *)my_pair);
17404  if (Cudd_IsComplement(root)) {
17405  res_pair.pos = my_pair->neg;
17406  res_pair.neg = my_pair->pos;
17407  } else {
17408  res_pair.pos = my_pair->pos;
17409  res_pair.neg = my_pair->neg;
17410  }
17411  return(res_pair);
17412 
17413  } /* end of getLargest */
17414 
17415 
17434  static DdNode *
17436  DdManager * manager,
17437  st_table * visited,
17438  DdNode * f,
17439  int cost)
17440  {
17441  DdNode *sol, *tmp;
17442  DdNode *my_dd, *T, *E;
17443  cuddPathPair *T_pair, *E_pair;
17444  int Tcost, Ecost;
17445  int complement;
17446 
17447  my_dd = Cudd_Regular(f);
17448  complement = Cudd_IsComplement(f);
17449 
17450  sol = one;
17451  cuddRef(sol);
17452 
17453  while (!cuddIsConstant(my_dd)) {
17454  Tcost = cost - 1;
17455  Ecost = cost - 1;
17456 
17457  T = cuddT(my_dd);
17458  E = cuddE(my_dd);
17459 
17460  if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
17461 
17462  if (!st_lookup(visited, Cudd_Regular(T), &T_pair)) return(NULL);
17463  if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
17464  (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
17465  tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
17466  if (tmp == NULL) {
17467  Cudd_RecursiveDeref(manager,sol);
17468  return(NULL);
17469  }
17470  cuddRef(tmp);
17471  Cudd_RecursiveDeref(manager,sol);
17472  sol = tmp;
17473 
17474  complement = Cudd_IsComplement(T);
17475  my_dd = Cudd_Regular(T);
17476  cost = Tcost;
17477  continue;
17478  }
17479  if (!st_lookup(visited, Cudd_Regular(E), &E_pair)) return(NULL);
17480  if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
17481  (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
17482  tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
17483  if (tmp == NULL) {
17484  Cudd_RecursiveDeref(manager,sol);
17485  return(NULL);
17486  }
17487  cuddRef(tmp);
17488  Cudd_RecursiveDeref(manager,sol);
17489  sol = tmp;
17490  complement = Cudd_IsComplement(E);
17491  my_dd = Cudd_Regular(E);
17492  cost = Ecost;
17493  continue;
17494  }
17495  (void) fprintf(manager->err,"We shouldn't be here!\n");
17496  manager->errorCode = CUDD_INTERNAL_ERROR;
17497  return(NULL);
17498  }
17499 
17500  cuddDeref(sol);
17501  return(sol);
17502 
17503  } /* end of getCube */
17504 
17505 
17520  static DdNode *
17522  DdManager *dd /* manager */,
17523  DdNode *lb /* cube to be expanded */,
17524  DdNode *ub /* upper bound cube */,
17525  DdNode *f /* function against which to expand */)
17526  {
17527  DdNode *one, *zero, *lbv, *lbvn, *lbnx, *ubv, *ubvn, *fv, *fvn, *res;
17528  DdNode *F, *UB, *LB, *t, *e;
17529  unsigned int top, toplb, topub, topf, index;
17530 
17531  statLine(dd);
17532  /* Terminal cases. */
17533  one = DD_ONE(dd);
17534  zero = Cudd_Not(one);
17535  assert(ub != zero && lb != zero);
17543  if (ub == f || f == one) return(ub);
17544  if (lb == f) return(lb);
17545  if (f == zero || ub == Cudd_Not(f) || lb == one || lb == Cudd_Not(f))
17546  return(zero);
17547  if (!Cudd_IsComplement(lb) && Cudd_IsComplement(f)) return(zero);
17548 
17549  /* Here lb and f are not constant. */
17550 
17551  /* Check cache. Since lb and ub are cubes, their local reference counts
17552  ** are always 1. Hence, we only check the reference count of f.
17553  */
17554  F = Cudd_Regular(f);
17555  if (F->ref != 1) {
17556  DdNode *tmp = cuddCacheLookup(dd, DD_BDD_MAX_EXP_TAG, lb, ub, f);
17557  if (tmp != NULL) {
17558  return(tmp);
17559  }
17560  }
17561 
17562  /* Compute cofactors. For lb we use the non-zero one in
17563  ** both branches of the recursion.
17564  */
17565  LB = Cudd_Regular(lb);
17566  UB = Cudd_Regular(ub);
17567  topf = dd->perm[F->index];
17568  toplb = dd->perm[LB->index];
17569  topub = (ub == one) ? CUDD_CONST_INDEX : dd->perm[UB->index];
17570  assert(toplb <= topub);
17571  top = ddMin(topf,toplb);
17572  if (toplb == top) {
17573  index = LB->index;
17574  lbv = cuddT(LB);
17575  lbvn = cuddE(LB);
17576  if (lb != LB) {
17577  lbv = Cudd_Not(lbv);
17578  lbvn = Cudd_Not(lbvn);
17579  }
17580  if (lbv == zero) {
17581  lbnx = lbvn;
17582  } else {
17583  lbnx = lbv;
17584  }
17585  } else {
17586  index = F->index;
17587  lbnx = lbv = lbvn = lb;
17588  }
17589  if (topub == top) {
17590  ubv = cuddT(UB);
17591  ubvn = cuddE(UB);
17592  if (ub != UB) {
17593  ubv = Cudd_Not(ubv);
17594  ubvn = Cudd_Not(ubvn);
17595  }
17596  } else {
17597  ubv = ubvn = ub;
17598  }
17599  if (topf == top) {
17600  fv = cuddT(F);
17601  fvn = cuddE(F);
17602  if (f != F) {
17603  fv = Cudd_Not(fv);
17604  fvn = Cudd_Not(fvn);
17605  }
17606  } else {
17607  fv = fvn = f;
17608  }
17609 
17610  /* Recursive calls. */
17611  if (ubv != zero) {
17612  t = ddBddMaximallyExpand(dd, lbnx, ubv, fv);
17613  if (t == NULL) return(NULL);
17614  } else {
17615  assert(topub == toplb && topub == top && lbv == zero);
17616  t = zero;
17617  }
17618  cuddRef(t);
17619 
17620  /* If the top variable appears only in lb, the positive and negative
17621  ** cofactors of each operand are the same. We want to avoid a
17622  ** needless recursive call, which would force us to give up the
17623  ** cache optimization trick based on reference counts.
17624  */
17625  if (ubv == ubvn && fv == fvn) {
17626  res = t;
17627  } else {
17628  if (ubvn != zero) {
17629  e = ddBddMaximallyExpand(dd, lbnx, ubvn, fvn);
17630  if (e == NULL) {
17631  Cudd_IterDerefBdd(dd,t);
17632  return(NULL);
17633  }
17634  } else {
17635  assert(topub == toplb && topub == top && lbvn == zero);
17636  e = zero;
17637  }
17638 
17639  if (t == e) {
17640  res = t;
17641  } else {
17642  cuddRef(e);
17643 
17644  if (toplb == top) {
17645  if (lbv == zero) {
17646  /* Top variable appears in negative phase. */
17647  if (t != one) {
17648  DdNode *newT;
17649  if (Cudd_IsComplement(t)) {
17650  newT = cuddUniqueInter(dd, index, Cudd_Not(t), zero);
17651  if (newT == NULL) {
17652  Cudd_IterDerefBdd(dd,t);
17653  Cudd_IterDerefBdd(dd,e);
17654  return(NULL);
17655  }
17656  newT = Cudd_Not(newT);
17657  } else {
17658  newT = cuddUniqueInter(dd, index, t, one);
17659  if (newT == NULL) {
17660  Cudd_IterDerefBdd(dd,t);
17661  Cudd_IterDerefBdd(dd,e);
17662  return(NULL);
17663  }
17664  }
17665  cuddRef(newT);
17666  cuddDeref(t);
17667  t = newT;
17668  }
17669  } else if (lbvn == zero) {
17670  /* Top variable appears in positive phase. */
17671  if (e != one) {
17672  DdNode *newE;
17673  newE = cuddUniqueInter(dd, index, one, e);
17674  if (newE == NULL) {
17675  Cudd_IterDerefBdd(dd,t);
17676  Cudd_IterDerefBdd(dd,e);
17677  return(NULL);
17678  }
17679  cuddRef(newE);
17680  cuddDeref(e);
17681  e = newE;
17682  }
17683  } else {
17684  /* Not a cube. */
17685  Cudd_IterDerefBdd(dd,t);
17686  Cudd_IterDerefBdd(dd,e);
17687  return(NULL);
17688  }
17689  }
17690 
17691  /* Combine results. */
17692  res = cuddBddAndRecur(dd, t, e);
17693  if (res == NULL) {
17694  Cudd_IterDerefBdd(dd,t);
17695  Cudd_IterDerefBdd(dd,e);
17696  return(NULL);
17697  }
17698  cuddRef(res);
17699  Cudd_IterDerefBdd(dd,t);
17700  Cudd_IterDerefBdd(dd,e);
17701  }
17702  }
17703 
17704  /* Cache result and return. */
17705  if (F->ref != 1) {
17706  cuddCacheInsert(dd, DD_BDD_MAX_EXP_TAG, lb, ub, f, res);
17707  }
17708  cuddDeref(res);
17709  return(res);
17710 
17711  } /* end of ddBddMaximallyExpand */
17712 
17713 
17729  static int
17731  DdManager *dd,
17732  DdNode *f,
17733  int *phases,
17734  st_table *table)
17735  {
17736  int positive, l, lT, lE;
17737  DdNode *one = DD_ONE(dd);
17738  DdNode *zero = Cudd_Not(one);
17739  DdNode *F, *fv, *fvn;
17740 
17741  if (st_lookup_int(table, f, &l)) {
17742  return(l);
17743  }
17744  if (f == one) {
17745  l = 0;
17746  } else if (f == zero) {
17747  l = DD_BIGGY;
17748  } else {
17749  F = Cudd_Regular(f);
17750  fv = cuddT(F);
17751  fvn = cuddE(F);
17752  if (f != F) {
17753  fv = Cudd_Not(fv);
17754  fvn = Cudd_Not(fvn);
17755  }
17756  lT = ddBddShortestPathUnate(dd, fv, phases, table);
17757  lE = ddBddShortestPathUnate(dd, fvn, phases, table);
17758  positive = phases[F->index];
17759  l = positive ? ddMin(lT+1, lE) : ddMin(lT, lE+1);
17760  }
17761  if (st_insert(table, f, (void *)(ptrint) l) == ST_OUT_OF_MEM) {
17762  return(CUDD_OUT_OF_MEM);
17763  }
17764  return(l);
17765 
17766  } /* end of ddShortestPathUnate */
17767 
17768 
17769 /* end of ddGetLargestCubeUnate */
17838 /*---------------------------------------------------------------------------*/
17839 /* Constant declarations */
17840 /*---------------------------------------------------------------------------*/
17841 
17842 #define MV_OOM (Move *)1
17843 
17844 /*---------------------------------------------------------------------------*/
17845 /* Stucture declarations */
17846 /*---------------------------------------------------------------------------*/
17847 
17848 /*---------------------------------------------------------------------------*/
17849 /* Type declarations */
17850 /*---------------------------------------------------------------------------*/
17851 
17852 /*---------------------------------------------------------------------------*/
17853 /* Variable declarations */
17854 /*---------------------------------------------------------------------------*/
17855 
17856 //#ifndef lint
17857 //static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.28 2012/02/05 01:07:19 fabio Exp $";
17858 //#endif
17859 
17860  static int *entry;
17861 
17862  extern int ddTotalNumberSwapping;
17863 #ifdef DD_STATS
17864  extern int ddTotalNISwaps;
17865 #endif
17866 
17867 /*---------------------------------------------------------------------------*/
17868 /* Macro declarations */
17869 /*---------------------------------------------------------------------------*/
17870 
17873 /*---------------------------------------------------------------------------*/
17874 /* Static function prototypes */
17875 /*---------------------------------------------------------------------------*/
17876 
17877  static int ddSymmUniqueCompare (int *ptrX, int *ptrY);
17878  static int ddSymmSiftingAux (DdManager *table, int x, int xLow, int xHigh);
17879  static int ddSymmSiftingConvAux (DdManager *table, int x, int xLow, int xHigh);
17880  static Move * ddSymmSiftingUp (DdManager *table, int y, int xLow);
17881  static Move * ddSymmSiftingDown (DdManager *table, int x, int xHigh);
17882  static int ddSymmGroupMove (DdManager *table, int x, int y, Move **moves);
17883  static int ddSymmGroupMoveBackward (DdManager *table, int x, int y);
17884  static int ddSymmSiftingBackward (DdManager *table, Move *moves, int size);
17885  static void ddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
17886 
17890 /*---------------------------------------------------------------------------*/
17891 /* Definition of exported functions */
17892 /*---------------------------------------------------------------------------*/
17893 
17894 
17895 /*---------------------------------------------------------------------------*/
17896 /* Definition of internal functions */
17897 /*---------------------------------------------------------------------------*/
17898 
17899 
17911  int
17913  DdManager * table,
17914  int x,
17915  int y)
17916  {
17917  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
17918  int comple; /* f0 is complemented */
17919  int xsymmy; /* x and y may be positively symmetric */
17920  int xsymmyp; /* x and y may be negatively symmetric */
17921  int arccount; /* number of arcs from layer x to layer y */
17922  int TotalRefCount; /* total reference count of layer y minus 1 */
17923  int yindex;
17924  int i;
17925  DdNodePtr *list;
17926  int slots;
17927  DdNode *sentinel = &(table->sentinel);
17928 #ifdef DD_DEBUG
17929  int xindex;
17930 #endif
17931 
17932  /* Checks that x and y are not the projection functions.
17933  ** For x it is sufficient to check whether there is only one
17934  ** node; indeed, if there is one node, it is the projection function
17935  ** and it cannot point to y. Hence, if y isn't just the projection
17936  ** function, it has one arc coming from a layer different from x.
17937  */
17938  if (table->subtables[x].keys == 1) {
17939  return(0);
17940  }
17941  yindex = table->invperm[y];
17942  if (table->subtables[y].keys == 1) {
17943  if (table->vars[yindex]->ref == 1)
17944  return(0);
17945  }
17946 
17947  xsymmy = xsymmyp = 1;
17948  arccount = 0;
17949  slots = table->subtables[x].slots;
17950  list = table->subtables[x].nodelist;
17951  for (i = 0; i < slots; i++) {
17952  f = list[i];
17953  while (f != sentinel) {
17954  /* Find f1, f0, f11, f10, f01, f00. */
17955  f1 = cuddT(f);
17956  f0 = Cudd_Regular(cuddE(f));
17957  comple = Cudd_IsComplement(cuddE(f));
17958  if ((int) f1->index == yindex) {
17959  arccount++;
17960  f11 = cuddT(f1); f10 = cuddE(f1);
17961  } else {
17962  if ((int) f0->index != yindex) {
17963  /* If f is an isolated projection function it is
17964  ** allowed to bypass layer y.
17965  */
17966  if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
17967  return(0); /* f bypasses layer y */
17968  }
17969  f11 = f10 = f1;
17970  }
17971  if ((int) f0->index == yindex) {
17972  arccount++;
17973  f01 = cuddT(f0); f00 = cuddE(f0);
17974  } else {
17975  f01 = f00 = f0;
17976  }
17977  if (comple) {
17978  f01 = Cudd_Not(f01);
17979  f00 = Cudd_Not(f00);
17980  }
17981 
17982  if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
17983  xsymmy &= f01 == f10;
17984  xsymmyp &= f11 == f00;
17985  if ((xsymmy == 0) && (xsymmyp == 0))
17986  return(0);
17987  }
17988 
17989  f = f->next;
17990  } /* while */
17991  } /* for */
17992 
17993  /* Calculate the total reference counts of y */
17994  TotalRefCount = -1; /* -1 for projection function */
17995  slots = table->subtables[y].slots;
17996  list = table->subtables[y].nodelist;
17997  for (i = 0; i < slots; i++) {
17998  f = list[i];
17999  while (f != sentinel) {
18000  TotalRefCount += f->ref;
18001  f = f->next;
18002  }
18003  }
18004 
18005 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
18006  if (arccount == TotalRefCount) {
18007  xindex = table->invperm[x];
18008  (void) fprintf(table->out,
18009  "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
18010  xindex,yindex,x,y);
18011  }
18012 #endif
18013 
18014  return(arccount == TotalRefCount);
18015 
18016  } /* end of cuddSymmCheck */
18017 
18018 
18041  int
18043  DdManager * table,
18044  int lower,
18045  int upper)
18046  {
18047  int i;
18048  int *var;
18049  int size;
18050  int x;
18051  int result;
18052  int symvars;
18053  int symgroups;
18054 #ifdef DD_STATS
18055  int previousSize;
18056 #endif
18057 
18058  size = table->size;
18059 
18060  /* Find order in which to sift variables. */
18061  var = NULL;
18062  entry = ALLOC(int,size);
18063  if (entry == NULL) {
18064  table->errorCode = CUDD_MEMORY_OUT;
18065  goto ddSymmSiftingOutOfMem;
18066  }
18067  var = ALLOC(int,size);
18068  if (var == NULL) {
18069  table->errorCode = CUDD_MEMORY_OUT;
18070  goto ddSymmSiftingOutOfMem;
18071  }
18072 
18073  for (i = 0; i < size; i++) {
18074  x = table->perm[i];
18075  entry[i] = table->subtables[x].keys;
18076  var[i] = i;
18077  }
18078 
18079  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
18080 
18081  /* Initialize the symmetry of each subtable to itself. */
18082  for (i = lower; i <= upper; i++) {
18083  table->subtables[i].next = i;
18084  }
18085 
18086  for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
18087  if (ddTotalNumberSwapping >= table->siftMaxSwap)
18088  break;
18089  if (util_cpu_time() - table->startTime > table->timeLimit) {
18090  table->autoDyn = 0; /* prevent further reordering */
18091  break;
18092  }
18093  x = table->perm[var[i]];
18094 #ifdef DD_STATS
18095  previousSize = table->keys - table->isolated;
18096 #endif
18097  if (x < lower || x > upper) continue;
18098  if (table->subtables[x].next == (unsigned) x) {
18099  result = ddSymmSiftingAux(table,x,lower,upper);
18100  if (!result) goto ddSymmSiftingOutOfMem;
18101 #ifdef DD_STATS
18102  if (table->keys < (unsigned) previousSize + table->isolated) {
18103  (void) fprintf(table->out,"-");
18104  } else if (table->keys > (unsigned) previousSize +
18105  table->isolated) {
18106  (void) fprintf(table->out,"+"); /* should never happen */
18107  } else {
18108  (void) fprintf(table->out,"=");
18109  }
18110  fflush(table->out);
18111 #endif
18112  }
18113  }
18114 
18115  FREE(var);
18116  FREE(entry);
18117 
18118  ddSymmSummary(table, lower, upper, &symvars, &symgroups);
18119 
18120 #ifdef DD_STATS
18121  (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
18122  symvars);
18123  (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
18124  symgroups);
18125 #endif
18126 
18127  return(1+symvars);
18128 
18129  ddSymmSiftingOutOfMem:
18130 
18131  if (entry != NULL) FREE(entry);
18132  if (var != NULL) FREE(var);
18133 
18134  return(0);
18135 
18136  } /* end of cuddSymmSifting */
18137 
18138 
18162  int
18164  DdManager * table,
18165  int lower,
18166  int upper)
18167  {
18168  int i;
18169  int *var;
18170  int size;
18171  int x;
18172  int result;
18173  int symvars;
18174  int symgroups;
18175  int classes;
18176  int initialSize;
18177 #ifdef DD_STATS
18178  int previousSize;
18179 #endif
18180 
18181  initialSize = table->keys - table->isolated;
18182 
18183  size = table->size;
18184 
18185  /* Find order in which to sift variables. */
18186  var = NULL;
18187  entry = ALLOC(int,size);
18188  if (entry == NULL) {
18189  table->errorCode = CUDD_MEMORY_OUT;
18190  goto ddSymmSiftingConvOutOfMem;
18191  }
18192  var = ALLOC(int,size);
18193  if (var == NULL) {
18194  table->errorCode = CUDD_MEMORY_OUT;
18195  goto ddSymmSiftingConvOutOfMem;
18196  }
18197 
18198  for (i = 0; i < size; i++) {
18199  x = table->perm[i];
18200  entry[i] = table->subtables[x].keys;
18201  var[i] = i;
18202  }
18203 
18204  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
18205 
18206  /* Initialize the symmetry of each subtable to itself
18207  ** for first pass of converging symmetric sifting.
18208  */
18209  for (i = lower; i <= upper; i++) {
18210  table->subtables[i].next = i;
18211  }
18212 
18213  for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
18214  if (ddTotalNumberSwapping >= table->siftMaxSwap)
18215  break;
18216  if (util_cpu_time() - table->startTime > table->timeLimit) {
18217  table->autoDyn = 0; /* prevent further reordering */
18218  break;
18219  }
18220  x = table->perm[var[i]];
18221  if (x < lower || x > upper) continue;
18222  /* Only sift if not in symmetry group already. */
18223  if (table->subtables[x].next == (unsigned) x) {
18224 #ifdef DD_STATS
18225  previousSize = table->keys - table->isolated;
18226 #endif
18227  result = ddSymmSiftingAux(table,x,lower,upper);
18228  if (!result) goto ddSymmSiftingConvOutOfMem;
18229 #ifdef DD_STATS
18230 if (table->keys < (unsigned) previousSize + table->isolated) {
18231 (void) fprintf(table->out,"-");
18232 } else if (table->keys > (unsigned) previousSize +
18233 table->isolated) {
18234 (void) fprintf(table->out,"+");
18235 } else {
18236 (void) fprintf(table->out,"=");
18237 }
18238 fflush(table->out);
18239 #endif
18240 }
18241 }
18242 
18243 /* Sifting now until convergence. */
18244 while ((unsigned) initialSize > table->keys - table->isolated) {
18245 initialSize = table->keys - table->isolated;
18246 #ifdef DD_STATS
18247 (void) fprintf(table->out,"\n");
18248 #endif
18249 /* Here we consider only one representative for each symmetry class. */
18250 for (x = lower, classes = 0; x <= upper; x++, classes++) {
18251 while ((unsigned) x < table->subtables[x].next) {
18252 x = table->subtables[x].next;
18253 }
18254 /* Here x is the largest index in a group.
18255 ** Groups consist of adjacent variables.
18256 ** Hence, the next increment of x will move it to a new group.
18257 */
18258 i = table->invperm[x];
18259 entry[i] = table->subtables[x].keys;
18260 var[classes] = i;
18261 }
18262 
18263 qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
18264 
18265 /* Now sift. */
18266 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
18267 if (ddTotalNumberSwapping >= table->siftMaxSwap)
18268 break;
18269 if (util_cpu_time() - table->startTime > table->timeLimit) {
18270 table->autoDyn = 0; /* prevent further reordering */
18271 break;
18272 }
18273 x = table->perm[var[i]];
18274 if ((unsigned) x >= table->subtables[x].next) {
18275 #ifdef DD_STATS
18276 previousSize = table->keys - table->isolated;
18277 #endif
18278 result = ddSymmSiftingConvAux(table,x,lower,upper);
18279 if (!result ) goto ddSymmSiftingConvOutOfMem;
18280 #ifdef DD_STATS
18281 if (table->keys < (unsigned) previousSize + table->isolated) {
18282 (void) fprintf(table->out,"-");
18283 } else if (table->keys > (unsigned) previousSize +
18284 table->isolated) {
18285 (void) fprintf(table->out,"+");
18286 } else {
18287 (void) fprintf(table->out,"=");
18288 }
18289 fflush(table->out);
18290 #endif
18291 }
18292 } /* for */
18293 }
18294 
18295 ddSymmSummary(table, lower, upper, &symvars, &symgroups);
18296 
18297 #ifdef DD_STATS
18298 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
18299 symvars);
18300 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
18301 symgroups);
18302 #endif
18303 
18304 FREE(var);
18305 FREE(entry);
18306 
18307 return(1+symvars);
18308 
18309 ddSymmSiftingConvOutOfMem:
18310 
18311 if (entry != NULL) FREE(entry);
18312 if (var != NULL) FREE(var);
18313 
18314 return(0);
18315 
18316 } /* end of cuddSymmSiftingConv */
18317 
18318 
18319 /*---------------------------------------------------------------------------*/
18320 /* Definition of static functions */
18321 /*---------------------------------------------------------------------------*/
18322 
18323 
18336 static int
18338 int * ptrX,
18339 int * ptrY)
18340 {
18341 #if 0
18342 if (entry[*ptrY] == entry[*ptrX]) {
18343 return((*ptrX) - (*ptrY));
18344 }
18345 #endif
18346 return(entry[*ptrY] - entry[*ptrX]);
18347 
18348 } /* end of ddSymmUniqueCompare */
18349 
18350 
18364 static int
18366 DdManager * table,
18367 int x,
18368 int xLow,
18369 int xHigh)
18370 {
18371 Move *move;
18372 Move *moveUp; /* list of up moves */
18373 Move *moveDown; /* list of down moves */
18374 int initialSize;
18375 int result;
18376 int i;
18377 int topbot; /* index to either top or bottom of symmetry group */
18378 int initGroupSize, finalGroupSize;
18379 
18380 
18381 #ifdef DD_DEBUG
18382 /* check for previously detected symmetry */
18383 assert(table->subtables[x].next == (unsigned) x);
18384 #endif
18385 
18386 initialSize = table->keys - table->isolated;
18387 
18388 moveDown = NULL;
18389 moveUp = NULL;
18390 
18391 if ((x - xLow) > (xHigh - x)) {
18392 /* Will go down first, unless x == xHigh:
18393 ** Look for consecutive symmetries above x.
18394 */
18395 for (i = x; i > xLow; i--) {
18396 if (!cuddSymmCheck(table,i-1,i))
18397 break;
18398 topbot = table->subtables[i-1].next; /* find top of i-1's group */
18399 table->subtables[i-1].next = i;
18400 table->subtables[x].next = topbot; /* x is bottom of group so its */
18401 /* next is top of i-1's group */
18402 i = topbot + 1; /* add 1 for i--; new i is top of symm group */
18403 }
18404 } else {
18405 /* Will go up first unless x == xlow:
18406 ** Look for consecutive symmetries below x.
18407 */
18408 for (i = x; i < xHigh; i++) {
18409 if (!cuddSymmCheck(table,i,i+1))
18410 break;
18411 /* find bottom of i+1's symm group */
18412 topbot = i + 1;
18413 while ((unsigned) topbot < table->subtables[topbot].next) {
18414 topbot = table->subtables[topbot].next;
18415 }
18416 table->subtables[topbot].next = table->subtables[i].next;
18417 table->subtables[i].next = i + 1;
18418 i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */
18419 }
18420 }
18421 
18422 /* Now x may be in the middle of a symmetry group.
18423 ** Find bottom of x's symm group.
18424 */
18425 while ((unsigned) x < table->subtables[x].next)
18426 x = table->subtables[x].next;
18427 
18428 if (x == xLow) { /* Sift down */
18429 
18430 #ifdef DD_DEBUG
18431 /* x must be a singleton */
18432 assert((unsigned) x == table->subtables[x].next);
18433 #endif
18434 if (x == xHigh) return(1); /* just one variable */
18435 
18436 initGroupSize = 1;
18437 
18438 moveDown = ddSymmSiftingDown(table,x,xHigh);
18439 /* after this point x --> xHigh, unless early term */
18440 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
18441 if (moveDown == NULL) return(1);
18442 
18443 x = moveDown->y;
18444 /* Find bottom of x's group */
18445 i = x;
18446 while ((unsigned) i < table->subtables[i].next) {
18447 i = table->subtables[i].next;
18448 }
18449 #ifdef DD_DEBUG
18450 /* x should be the top of the symmetry group and i the bottom */
18451 assert((unsigned) i >= table->subtables[i].next);
18452 assert((unsigned) x == table->subtables[i].next);
18453 #endif
18454 finalGroupSize = i - x + 1;
18455 
18456 if (initGroupSize == finalGroupSize) {
18457 /* No new symmetry groups detected, return to best position */
18458 result = ddSymmSiftingBackward(table,moveDown,initialSize);
18459 } else {
18460 initialSize = table->keys - table->isolated;
18461 moveUp = ddSymmSiftingUp(table,x,xLow);
18462 result = ddSymmSiftingBackward(table,moveUp,initialSize);
18463 }
18464 if (!result) goto ddSymmSiftingAuxOutOfMem;
18465 
18466 } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
18467 /* Find top of x's symm group */
18468 i = x; /* bottom */
18469 x = table->subtables[x].next; /* top */
18470 
18471 if (x == xLow) return(1); /* just one big group */
18472 
18473 initGroupSize = i - x + 1;
18474 
18475 moveUp = ddSymmSiftingUp(table,x,xLow);
18476 /* after this point x --> xLow, unless early term */
18477 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
18478 if (moveUp == NULL) return(1);
18479 
18480 x = moveUp->x;
18481 /* Find top of x's group */
18482 i = table->subtables[x].next;
18483 #ifdef DD_DEBUG
18484 /* x should be the bottom of the symmetry group and i the top */
18485 assert((unsigned) x >= table->subtables[x].next);
18486 assert((unsigned) i == table->subtables[x].next);
18487 #endif
18488 finalGroupSize = x - i + 1;
18489 
18490 if (initGroupSize == finalGroupSize) {
18491 /* No new symmetry groups detected, return to best position */
18492 result = ddSymmSiftingBackward(table,moveUp,initialSize);
18493 } else {
18494 initialSize = table->keys - table->isolated;
18495 moveDown = ddSymmSiftingDown(table,x,xHigh);
18496 result = ddSymmSiftingBackward(table,moveDown,initialSize);
18497 }
18498 if (!result) goto ddSymmSiftingAuxOutOfMem;
18499 
18500 } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
18501 
18502 moveDown = ddSymmSiftingDown(table,x,xHigh);
18503 /* at this point x == xHigh, unless early term */
18504 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
18505 
18506 if (moveDown != NULL) {
18507 x = moveDown->y; /* x is top here */
18508 i = x;
18509 while ((unsigned) i < table->subtables[i].next) {
18510 i = table->subtables[i].next;
18511 }
18512 } else {
18513 i = x;
18514 while ((unsigned) i < table->subtables[i].next) {
18515 i = table->subtables[i].next;
18516 }
18517 x = table->subtables[i].next;
18518 }
18519 #ifdef DD_DEBUG
18520 /* x should be the top of the symmetry group and i the bottom */
18521 assert((unsigned) i >= table->subtables[i].next);
18522 assert((unsigned) x == table->subtables[i].next);
18523 #endif
18524 initGroupSize = i - x + 1;
18525 
18526 moveUp = ddSymmSiftingUp(table,x,xLow);
18527 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
18528 
18529 if (moveUp != NULL) {
18530 x = moveUp->x;
18531 i = table->subtables[x].next;
18532 } else {
18533 i = x;
18534 while ((unsigned) x < table->subtables[x].next)
18535 x = table->subtables[x].next;
18536 }
18537 #ifdef DD_DEBUG
18538 /* x should be the bottom of the symmetry group and i the top */
18539 assert((unsigned) x >= table->subtables[x].next);
18540 assert((unsigned) i == table->subtables[x].next);
18541 #endif
18542 finalGroupSize = x - i + 1;
18543 
18544 if (initGroupSize == finalGroupSize) {
18545 /* No new symmetry groups detected, return to best position */
18546 result = ddSymmSiftingBackward(table,moveUp,initialSize);
18547 } else {
18548 while (moveDown != NULL) {
18549 move = moveDown->next;
18550 cuddDeallocMove(table, moveDown);
18551 moveDown = move;
18552 }
18553 initialSize = table->keys - table->isolated;
18554 moveDown = ddSymmSiftingDown(table,x,xHigh);
18555 result = ddSymmSiftingBackward(table,moveDown,initialSize);
18556 }
18557 if (!result) goto ddSymmSiftingAuxOutOfMem;
18558 
18559 } else { /* moving up first: shorter */
18560 /* Find top of x's symmetry group */
18561 x = table->subtables[x].next;
18562 
18563 moveUp = ddSymmSiftingUp(table,x,xLow);
18564 /* at this point x == xHigh, unless early term */
18565 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
18566 
18567 if (moveUp != NULL) {
18568 x = moveUp->x;
18569 i = table->subtables[x].next;
18570 } else {
18571 while ((unsigned) x < table->subtables[x].next)
18572 x = table->subtables[x].next;
18573 i = table->subtables[x].next;
18574 }
18575 #ifdef DD_DEBUG
18576 /* x is bottom of the symmetry group and i is top */
18577 assert((unsigned) x >= table->subtables[x].next);
18578 assert((unsigned) i == table->subtables[x].next);
18579 #endif
18580 initGroupSize = x - i + 1;
18581 
18582 moveDown = ddSymmSiftingDown(table,x,xHigh);
18583 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
18584 
18585 if (moveDown != NULL) {
18586 x = moveDown->y;
18587 i = x;
18588 while ((unsigned) i < table->subtables[i].next) {
18589 i = table->subtables[i].next;
18590 }
18591 } else {
18592 i = x;
18593 x = table->subtables[x].next;
18594 }
18595 #ifdef DD_DEBUG
18596 /* x should be the top of the symmetry group and i the bottom */
18597 assert((unsigned) i >= table->subtables[i].next);
18598 assert((unsigned) x == table->subtables[i].next);
18599 #endif
18600 finalGroupSize = i - x + 1;
18601 
18602 if (initGroupSize == finalGroupSize) {
18603 /* No new symmetries detected, go back to best position */
18604 result = ddSymmSiftingBackward(table,moveDown,initialSize);
18605 } else {
18606 while (moveUp != NULL) {
18607 move = moveUp->next;
18608 cuddDeallocMove(table, moveUp);
18609 moveUp = move;
18610 }
18611 initialSize = table->keys - table->isolated;
18612 moveUp = ddSymmSiftingUp(table,x,xLow);
18613 result = ddSymmSiftingBackward(table,moveUp,initialSize);
18614 }
18615 if (!result) goto ddSymmSiftingAuxOutOfMem;
18616 }
18617 
18618 while (moveDown != NULL) {
18619 move = moveDown->next;
18620 cuddDeallocMove(table, moveDown);
18621 moveDown = move;
18622 }
18623 while (moveUp != NULL) {
18624 move = moveUp->next;
18625 cuddDeallocMove(table, moveUp);
18626 moveUp = move;
18627 }
18628 
18629 return(1);
18630 
18631 ddSymmSiftingAuxOutOfMem:
18632 if (moveDown != MV_OOM) {
18633 while (moveDown != NULL) {
18634 move = moveDown->next;
18635 cuddDeallocMove(table, moveDown);
18636 moveDown = move;
18637 }
18638 }
18639 if (moveUp != MV_OOM) {
18640 while (moveUp != NULL) {
18641 move = moveUp->next;
18642 cuddDeallocMove(table, moveUp);
18643 moveUp = move;
18644 }
18645 }
18646 
18647 return(0);
18648 
18649 } /* end of ddSymmSiftingAux */
18650 
18651 
18666 static int
18668 DdManager * table,
18669 int x,
18670 int xLow,
18671 int xHigh)
18672 {
18673 Move *move;
18674 Move *moveUp; /* list of up moves */
18675 Move *moveDown; /* list of down moves */
18676 int initialSize;
18677 int result;
18678 int i;
18679 int initGroupSize, finalGroupSize;
18680 
18681 
18682 initialSize = table->keys - table->isolated;
18683 
18684 moveDown = NULL;
18685 moveUp = NULL;
18686 
18687 if (x == xLow) { /* Sift down */
18688 #ifdef DD_DEBUG
18689 /* x is bottom of symmetry group */
18690 assert((unsigned) x >= table->subtables[x].next);
18691 #endif
18692 i = table->subtables[x].next;
18693 initGroupSize = x - i + 1;
18694 
18695 moveDown = ddSymmSiftingDown(table,x,xHigh);
18696 /* at this point x == xHigh, unless early term */
18697 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
18698 if (moveDown == NULL) return(1);
18699 
18700 x = moveDown->y;
18701 i = x;
18702 while ((unsigned) i < table->subtables[i].next) {
18703 i = table->subtables[i].next;
18704 }
18705 #ifdef DD_DEBUG
18706 /* x should be the top of the symmetric group and i the bottom */
18707 assert((unsigned) i >= table->subtables[i].next);
18708 assert((unsigned) x == table->subtables[i].next);
18709 #endif
18710 finalGroupSize = i - x + 1;
18711 
18712 if (initGroupSize == finalGroupSize) {
18713 /* No new symmetries detected, go back to best position */
18714 result = ddSymmSiftingBackward(table,moveDown,initialSize);
18715 } else {
18716 initialSize = table->keys - table->isolated;
18717 moveUp = ddSymmSiftingUp(table,x,xLow);
18718 result = ddSymmSiftingBackward(table,moveUp,initialSize);
18719 }
18720 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
18721 
18722 } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
18723 /* Find top of x's symm group */
18724 while ((unsigned) x < table->subtables[x].next)
18725 x = table->subtables[x].next;
18726 i = x; /* bottom */
18727 x = table->subtables[x].next; /* top */
18728 
18729 if (x == xLow) return(1);
18730 
18731 initGroupSize = i - x + 1;
18732 
18733 moveUp = ddSymmSiftingUp(table,x,xLow);
18734 /* at this point x == xLow, unless early term */
18735 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
18736 if (moveUp == NULL) return(1);
18737 
18738 x = moveUp->x;
18739 i = table->subtables[x].next;
18740 #ifdef DD_DEBUG
18741 /* x should be the bottom of the symmetry group and i the top */
18742 assert((unsigned) x >= table->subtables[x].next);
18743 assert((unsigned) i == table->subtables[x].next);
18744 #endif
18745 finalGroupSize = x - i + 1;
18746 
18747 if (initGroupSize == finalGroupSize) {
18748 /* No new symmetry groups detected, return to best position */
18749 result = ddSymmSiftingBackward(table,moveUp,initialSize);
18750 } else {
18751 initialSize = table->keys - table->isolated;
18752 moveDown = ddSymmSiftingDown(table,x,xHigh);
18753 result = ddSymmSiftingBackward(table,moveDown,initialSize);
18754 }
18755 if (!result)
18756 goto ddSymmSiftingConvAuxOutOfMem;
18757 
18758 } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
18759 moveDown = ddSymmSiftingDown(table,x,xHigh);
18760 /* at this point x == xHigh, unless early term */
18761 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
18762 
18763 if (moveDown != NULL) {
18764 x = moveDown->y;
18765 i = x;
18766 while ((unsigned) i < table->subtables[i].next) {
18767 i = table->subtables[i].next;
18768 }
18769 } else {
18770 while ((unsigned) x < table->subtables[x].next)
18771 x = table->subtables[x].next;
18772 i = x;
18773 x = table->subtables[x].next;
18774 }
18775 #ifdef DD_DEBUG
18776 /* x should be the top of the symmetry group and i the bottom */
18777 assert((unsigned) i >= table->subtables[i].next);
18778 assert((unsigned) x == table->subtables[i].next);
18779 #endif
18780 initGroupSize = i - x + 1;
18781 
18782 moveUp = ddSymmSiftingUp(table,x,xLow);
18783 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
18784 
18785 if (moveUp != NULL) {
18786 x = moveUp->x;
18787 i = table->subtables[x].next;
18788 } else {
18789 i = x;
18790 while ((unsigned) x < table->subtables[x].next)
18791 x = table->subtables[x].next;
18792 }
18793 #ifdef DD_DEBUG
18794 /* x should be the bottom of the symmetry group and i the top */
18795 assert((unsigned) x >= table->subtables[x].next);
18796 assert((unsigned) i == table->subtables[x].next);
18797 #endif
18798 finalGroupSize = x - i + 1;
18799 
18800 if (initGroupSize == finalGroupSize) {
18801 /* No new symmetry groups detected, return to best position */
18802 result = ddSymmSiftingBackward(table,moveUp,initialSize);
18803 } else {
18804 while (moveDown != NULL) {
18805 move = moveDown->next;
18806 cuddDeallocMove(table, moveDown);
18807 moveDown = move;
18808 }
18809 initialSize = table->keys - table->isolated;
18810 moveDown = ddSymmSiftingDown(table,x,xHigh);
18811 result = ddSymmSiftingBackward(table,moveDown,initialSize);
18812 }
18813 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
18814 
18815 } else { /* moving up first: shorter */
18816 /* Find top of x's symmetry group */
18817 x = table->subtables[x].next;
18818 
18819 moveUp = ddSymmSiftingUp(table,x,xLow);
18820 /* at this point x == xHigh, unless early term */
18821 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
18822 
18823 if (moveUp != NULL) {
18824 x = moveUp->x;
18825 i = table->subtables[x].next;
18826 } else {
18827 i = x;
18828 while ((unsigned) x < table->subtables[x].next)
18829 x = table->subtables[x].next;
18830 }
18831 #ifdef DD_DEBUG
18832 /* x is bottom of the symmetry group and i is top */
18833 assert((unsigned) x >= table->subtables[x].next);
18834 assert((unsigned) i == table->subtables[x].next);
18835 #endif
18836 initGroupSize = x - i + 1;
18837 
18838 moveDown = ddSymmSiftingDown(table,x,xHigh);
18839 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
18840 
18841 if (moveDown != NULL) {
18842 x = moveDown->y;
18843 i = x;
18844 while ((unsigned) i < table->subtables[i].next) {
18845 i = table->subtables[i].next;
18846 }
18847 } else {
18848 i = x;
18849 x = table->subtables[x].next;
18850 }
18851 #ifdef DD_DEBUG
18852 /* x should be the top of the symmetry group and i the bottom */
18853 assert((unsigned) i >= table->subtables[i].next);
18854 assert((unsigned) x == table->subtables[i].next);
18855 #endif
18856 finalGroupSize = i - x + 1;
18857 
18858 if (initGroupSize == finalGroupSize) {
18859 /* No new symmetries detected, go back to best position */
18860 result = ddSymmSiftingBackward(table,moveDown,initialSize);
18861 } else {
18862 while (moveUp != NULL) {
18863 move = moveUp->next;
18864 cuddDeallocMove(table, moveUp);
18865 moveUp = move;
18866 }
18867 initialSize = table->keys - table->isolated;
18868 moveUp = ddSymmSiftingUp(table,x,xLow);
18869 result = ddSymmSiftingBackward(table,moveUp,initialSize);
18870 }
18871 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
18872 }
18873 
18874 while (moveDown != NULL) {
18875 move = moveDown->next;
18876 cuddDeallocMove(table, moveDown);
18877 moveDown = move;
18878 }
18879 while (moveUp != NULL) {
18880 move = moveUp->next;
18881 cuddDeallocMove(table, moveUp);
18882 moveUp = move;
18883 }
18884 
18885 return(1);
18886 
18887 ddSymmSiftingConvAuxOutOfMem:
18888 if (moveDown != MV_OOM) {
18889 while (moveDown != NULL) {
18890 move = moveDown->next;
18891 cuddDeallocMove(table, moveDown);
18892 moveDown = move;
18893 }
18894 }
18895 if (moveUp != MV_OOM) {
18896 while (moveUp != NULL) {
18897 move = moveUp->next;
18898 cuddDeallocMove(table, moveUp);
18899 moveUp = move;
18900 }
18901 }
18902 
18903 return(0);
18904 
18905 } /* end of ddSymmSiftingConvAux */
18906 
18907 
18923 static Move *
18925 DdManager * table,
18926 int y,
18927 int xLow)
18928 {
18929 Move *moves;
18930 Move *move;
18931 int x;
18932 int size;
18933 int i;
18934 int gxtop,gybot;
18935 int limitSize;
18936 int xindex, yindex;
18937 int zindex;
18938 int z;
18939 int isolated;
18940 int L; /* lower bound on DD size */
18941 #ifdef DD_DEBUG
18942 int checkL;
18943 #endif
18944 
18945 
18946 moves = NULL;
18947 yindex = table->invperm[y];
18948 
18949 /* Initialize the lower bound.
18950 ** The part of the DD below the bottom of y' group will not change.
18951 ** The part of the DD above y that does not interact with y will not
18952 ** change. The rest may vanish in the best case, except for
18953 ** the nodes at level xLow, which will not vanish, regardless.
18954 */
18955 limitSize = L = table->keys - table->isolated;
18956 gybot = y;
18957 while ((unsigned) gybot < table->subtables[gybot].next)
18958 gybot = table->subtables[gybot].next;
18959 for (z = xLow + 1; z <= gybot; z++) {
18960 zindex = table->invperm[z];
18961 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
18962 isolated = table->vars[zindex]->ref == 1;
18963 L -= table->subtables[z].keys - isolated;
18964 }
18965 }
18966 
18967 x = cuddNextLow(table,y);
18968 while (x >= xLow && L <= limitSize) {
18969 #ifdef DD_DEBUG
18970 gybot = y;
18971 while ((unsigned) gybot < table->subtables[gybot].next)
18972 gybot = table->subtables[gybot].next;
18973 checkL = table->keys - table->isolated;
18974 for (z = xLow + 1; z <= gybot; z++) {
18975 zindex = table->invperm[z];
18976 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
18977 isolated = table->vars[zindex]->ref == 1;
18978 checkL -= table->subtables[z].keys - isolated;
18979 }
18980 }
18981 assert(L == checkL);
18982 #endif
18983 gxtop = table->subtables[x].next;
18984 if (cuddSymmCheck(table,x,y)) {
18985 /* Symmetry found, attach symm groups */
18986 table->subtables[x].next = y;
18987 i = table->subtables[y].next;
18988 while (table->subtables[i].next != (unsigned) y)
18989 i = table->subtables[i].next;
18990 table->subtables[i].next = gxtop;
18991 } else if (table->subtables[x].next == (unsigned) x &&
18992 table->subtables[y].next == (unsigned) y) {
18993 /* x and y have self symmetry */
18994 xindex = table->invperm[x];
18995 size = cuddSwapInPlace(table,x,y);
18996 #ifdef DD_DEBUG
18997 assert(table->subtables[x].next == (unsigned) x);
18998 assert(table->subtables[y].next == (unsigned) y);
18999 #endif
19000 if (size == 0) goto ddSymmSiftingUpOutOfMem;
19001 /* Update the lower bound. */
19002 if (cuddTestInteract(table,xindex,yindex)) {
19003 isolated = table->vars[xindex]->ref == 1;
19004 L += table->subtables[y].keys - isolated;
19005 }
19006 move = (Move *) cuddDynamicAllocNode(table);
19007 if (move == NULL) goto ddSymmSiftingUpOutOfMem;
19008 move->x = x;
19009 move->y = y;
19010 move->size = size;
19011 move->next = moves;
19012 moves = move;
19013 if ((double) size > (double) limitSize * table->maxGrowth)
19014 return(moves);
19015 if (size < limitSize) limitSize = size;
19016 } else { /* Group move */
19017 size = ddSymmGroupMove(table,x,y,&moves);
19018 if (size == 0) goto ddSymmSiftingUpOutOfMem;
19019 /* Update the lower bound. */
19020 z = moves->y;
19021 do {
19022 zindex = table->invperm[z];
19023 if (cuddTestInteract(table,zindex,yindex)) {
19024 isolated = table->vars[zindex]->ref == 1;
19025 L += table->subtables[z].keys - isolated;
19026 }
19027 z = table->subtables[z].next;
19028 } while (z != (int) moves->y);
19029 if ((double) size > (double) limitSize * table->maxGrowth)
19030 return(moves);
19031 if (size < limitSize) limitSize = size;
19032 }
19033 y = gxtop;
19034 x = cuddNextLow(table,y);
19035 }
19036 
19037 return(moves);
19038 
19039 ddSymmSiftingUpOutOfMem:
19040 while (moves != NULL) {
19041 move = moves->next;
19042 cuddDeallocMove(table, moves);
19043 moves = move;
19044 }
19045 return(MV_OOM);
19046 
19047 } /* end of ddSymmSiftingUp */
19048 
19049 
19065 static Move *
19067 DdManager * table,
19068 int x,
19069 int xHigh)
19070 {
19071 Move *moves;
19072 Move *move;
19073 int y;
19074 int size;
19075 int limitSize;
19076 int gxtop,gybot;
19077 int R; /* upper bound on node decrease */
19078 int xindex, yindex;
19079 int isolated;
19080 int z;
19081 int zindex;
19082 #ifdef DD_DEBUG
19083 int checkR;
19084 #endif
19085 
19086 moves = NULL;
19087 /* Initialize R */
19088 xindex = table->invperm[x];
19089 gxtop = table->subtables[x].next;
19090 limitSize = size = table->keys - table->isolated;
19091 R = 0;
19092 for (z = xHigh; z > gxtop; z--) {
19093 zindex = table->invperm[z];
19094 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
19095 isolated = table->vars[zindex]->ref == 1;
19096 R += table->subtables[z].keys - isolated;
19097 }
19098 }
19099 
19100 y = cuddNextHigh(table,x);
19101 while (y <= xHigh && size - R < limitSize) {
19102 #ifdef DD_DEBUG
19103 gxtop = table->subtables[x].next;
19104 checkR = 0;
19105 for (z = xHigh; z > gxtop; z--) {
19106 zindex = table->invperm[z];
19107 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
19108 isolated = table->vars[zindex]->ref == 1;
19109 checkR += table->subtables[z].keys - isolated;
19110 }
19111 }
19112 assert(R == checkR);
19113 #endif
19114 gybot = table->subtables[y].next;
19115 while (table->subtables[gybot].next != (unsigned) y)
19116 gybot = table->subtables[gybot].next;
19117 if (cuddSymmCheck(table,x,y)) {
19118 /* Symmetry found, attach symm groups */
19119 gxtop = table->subtables[x].next;
19120 table->subtables[x].next = y;
19121 table->subtables[gybot].next = gxtop;
19122 } else if (table->subtables[x].next == (unsigned) x &&
19123 table->subtables[y].next == (unsigned) y) {
19124 /* x and y have self symmetry */
19125 /* Update upper bound on node decrease. */
19126 yindex = table->invperm[y];
19127 if (cuddTestInteract(table,xindex,yindex)) {
19128 isolated = table->vars[yindex]->ref == 1;
19129 R -= table->subtables[y].keys - isolated;
19130 }
19131 size = cuddSwapInPlace(table,x,y);
19132 #ifdef DD_DEBUG
19133 assert(table->subtables[x].next == (unsigned) x);
19134 assert(table->subtables[y].next == (unsigned) y);
19135 #endif
19136 if (size == 0) goto ddSymmSiftingDownOutOfMem;
19137 move = (Move *) cuddDynamicAllocNode(table);
19138 if (move == NULL) goto ddSymmSiftingDownOutOfMem;
19139 move->x = x;
19140 move->y = y;
19141 move->size = size;
19142 move->next = moves;
19143 moves = move;
19144 if ((double) size > (double) limitSize * table->maxGrowth)
19145 return(moves);
19146 if (size < limitSize) limitSize = size;
19147 } else { /* Group move */
19148 /* Update upper bound on node decrease: first phase. */
19149 gxtop = table->subtables[x].next;
19150 z = gxtop + 1;
19151 do {
19152 zindex = table->invperm[z];
19153 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
19154 isolated = table->vars[zindex]->ref == 1;
19155 R -= table->subtables[z].keys - isolated;
19156 }
19157 z++;
19158 } while (z <= gybot);
19159 size = ddSymmGroupMove(table,x,y,&moves);
19160 if (size == 0) goto ddSymmSiftingDownOutOfMem;
19161 if ((double) size > (double) limitSize * table->maxGrowth)
19162 return(moves);
19163 if (size < limitSize) limitSize = size;
19164 /* Update upper bound on node decrease: second phase. */
19165 gxtop = table->subtables[gybot].next;
19166 for (z = gxtop + 1; z <= gybot; z++) {
19167 zindex = table->invperm[z];
19168 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
19169 isolated = table->vars[zindex]->ref == 1;
19170 R += table->subtables[z].keys - isolated;
19171 }
19172 }
19173 }
19174 x = gybot;
19175 y = cuddNextHigh(table,x);
19176 }
19177 
19178 return(moves);
19179 
19180 ddSymmSiftingDownOutOfMem:
19181 while (moves != NULL) {
19182 move = moves->next;
19183 cuddDeallocMove(table, moves);
19184 moves = move;
19185 }
19186 return(MV_OOM);
19187 
19188 } /* end of ddSymmSiftingDown */
19189 
19190 
19203 static int
19205 DdManager * table,
19206 int x,
19207 int y,
19208 Move ** moves)
19209 {
19210 Move *move;
19211 int size;
19212 int i,j;
19213 int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
19214 int swapx,swapy;
19215 
19216 #ifdef DD_DEBUG
19217 assert(x < y); /* we assume that x < y */
19218 #endif
19219 /* Find top, bottom, and size for the two groups. */
19220 xbot = x;
19221 xtop = table->subtables[x].next;
19222 xsize = xbot - xtop + 1;
19223 ybot = y;
19224 while ((unsigned) ybot < table->subtables[ybot].next)
19225 ybot = table->subtables[ybot].next;
19226 ytop = y;
19227 ysize = ybot - ytop + 1;
19228 
19229 /* Sift the variables of the second group up through the first group. */
19230 for (i = 1; i <= ysize; i++) {
19231 for (j = 1; j <= xsize; j++) {
19232 size = cuddSwapInPlace(table,x,y);
19233 if (size == 0) return(0);
19234 swapx = x; swapy = y;
19235 y = x;
19236 x = y - 1;
19237 }
19238 y = ytop + i;
19239 x = y - 1;
19240 }
19241 
19242 /* fix symmetries */
19243 y = xtop; /* ytop is now where xtop used to be */
19244 for (i = 0; i < ysize-1 ; i++) {
19245 table->subtables[y].next = y + 1;
19246 y = y + 1;
19247 }
19248 table->subtables[y].next = xtop; /* y is bottom of its group, join */
19249 /* its symmetry to top of its group */
19250 x = y + 1;
19251 newxtop = x;
19252 for (i = 0; i < xsize - 1 ; i++) {
19253 table->subtables[x].next = x + 1;
19254 x = x + 1;
19255 }
19256 table->subtables[x].next = newxtop; /* x is bottom of its group, join */
19257 /* its symmetry to top of its group */
19258 /* Store group move */
19259 move = (Move *) cuddDynamicAllocNode(table);
19260 if (move == NULL) return(0);
19261 move->x = swapx;
19262 move->y = swapy;
19263 move->size = size;
19264 move->next = *moves;
19265 *moves = move;
19266 
19267 return(size);
19268 
19269 } /* end of ddSymmGroupMove */
19270 
19271 
19284 static int
19286 DdManager * table,
19287 int x,
19288 int y)
19289 {
19290 int size;
19291 int i,j;
19292 int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
19293 
19294 #ifdef DD_DEBUG
19295 assert(x < y); /* We assume that x < y */
19296 #endif
19297 
19298 /* Find top, bottom, and size for the two groups. */
19299 xbot = x;
19300 xtop = table->subtables[x].next;
19301 xsize = xbot - xtop + 1;
19302 ybot = y;
19303 while ((unsigned) ybot < table->subtables[ybot].next)
19304 ybot = table->subtables[ybot].next;
19305 ytop = y;
19306 ysize = ybot - ytop + 1;
19307 
19308 /* Sift the variables of the second group up through the first group. */
19309 for (i = 1; i <= ysize; i++) {
19310 for (j = 1; j <= xsize; j++) {
19311 size = cuddSwapInPlace(table,x,y);
19312 if (size == 0) return(0);
19313 y = x;
19314 x = cuddNextLow(table,y);
19315 }
19316 y = ytop + i;
19317 x = y - 1;
19318 }
19319 
19320 /* Fix symmetries. */
19321 y = xtop;
19322 for (i = 0; i < ysize-1 ; i++) {
19323 table->subtables[y].next = y + 1;
19324 y = y + 1;
19325 }
19326 table->subtables[y].next = xtop; /* y is bottom of its group, join */
19327 /* its symmetry to top of its group */
19328 x = y + 1;
19329 newxtop = x;
19330 for (i = 0; i < xsize-1 ; i++) {
19331 table->subtables[x].next = x + 1;
19332 x = x + 1;
19333 }
19334 table->subtables[x].next = newxtop; /* x is bottom of its group, join */
19335 /* its symmetry to top of its group */
19336 
19337 return(size);
19338 
19339 } /* end of ddSymmGroupMoveBackward */
19340 
19341 
19355 static int
19357 DdManager * table,
19358 Move * moves,
19359 int size)
19360 {
19361 Move *move;
19362 int res;
19363 
19364 for (move = moves; move != NULL; move = move->next) {
19365 if (move->size < size) {
19366 size = move->size;
19367 }
19368 }
19369 
19370 for (move = moves; move != NULL; move = move->next) {
19371 if (move->size == size) return(1);
19372 if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) {
19373 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
19374 #ifdef DD_DEBUG
19375 assert(table->subtables[move->x].next == move->x);
19376 assert(table->subtables[move->y].next == move->y);
19377 #endif
19378 } else { /* Group move necessary */
19379 res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y);
19380 }
19381 if (!res) return(0);
19382 }
19383 
19384 return(1);
19385 
19386 } /* end of ddSymmSiftingBackward */
19387 
19388 
19399 static void
19401 DdManager * table,
19402 int lower,
19403 int upper,
19404 int * symvars,
19405 int * symgroups)
19406 {
19407 int i,x,gbot;
19408 int TotalSymm = 0;
19409 int TotalSymmGroups = 0;
19410 
19411 for (i = lower; i <= upper; i++) {
19412 if (table->subtables[i].next != (unsigned) i) {
19413 TotalSymmGroups++;
19414 x = i;
19415 do {
19416 TotalSymm++;
19417 gbot = x;
19418 x = table->subtables[x].next;
19419 } while (x != i);
19420 #ifdef DD_DEBUG
19421 assert(table->subtables[gbot].next == (unsigned) i);
19422 #endif
19423 i = gbot;
19424 }
19425 }
19426 *symvars = TotalSymm;
19427 *symgroups = TotalSymmGroups;
19428 
19429 return;
19430 
19431 } /* end of ddSymmSummary */
19432 
19517 /*---------------------------------------------------------------------------*/
19518 /* Constant declarations */
19519 /*---------------------------------------------------------------------------*/
19520 
19521 #ifndef DD_UNSORTED_FREE_LIST
19522 #ifdef DD_RED_BLACK_FREE_LIST
19523 /* Constants for red/black trees. */
19524 #define DD_STACK_SIZE 128
19525 #define DD_RED 0
19526 #define DD_BLACK 1
19527 #define DD_PAGE_SIZE 8192
19528 #define DD_PAGE_MASK ~(DD_PAGE_SIZE - 1)
19529 #endif
19530 #endif
19531 
19532 /*---------------------------------------------------------------------------*/
19533 /* Stucture declarations */
19534 /*---------------------------------------------------------------------------*/
19535 
19536 /* This is a hack for when CUDD_VALUE_TYPE is double */
19537 typedef union hack {
19539 unsigned int bits[2];
19540 } hack;
19541 
19542 /*---------------------------------------------------------------------------*/
19543 /* Type declarations */
19544 /*---------------------------------------------------------------------------*/
19545 
19546 /*---------------------------------------------------------------------------*/
19547 /* Variable declarations */
19548 /*---------------------------------------------------------------------------*/
19549 
19550 //#ifndef lint
19551 //static char rcsid[] DD_UNUSED = "$Id: cuddTable.c,v 1.126 2012/02/05 01:07:19 fabio Exp $";
19552 //#endif
19553 
19554 /*---------------------------------------------------------------------------*/
19555 /* Macro declarations */
19556 /*---------------------------------------------------------------------------*/
19557 
19558 
19559 #ifndef DD_UNSORTED_FREE_LIST
19560 #ifdef DD_RED_BLACK_FREE_LIST
19561 /* Macros for red/black trees. */
19562 #define DD_INSERT_COMPARE(x,y) \
19563  (((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK))
19564 #define DD_COLOR(p) ((p)->index)
19565 #define DD_IS_BLACK(p) ((p)->index == DD_BLACK)
19566 #define DD_IS_RED(p) ((p)->index == DD_RED)
19567 #define DD_LEFT(p) cuddT(p)
19568 #define DD_RIGHT(p) cuddE(p)
19569 #define DD_NEXT(p) ((p)->next)
19570 #endif
19571 #endif
19572 
19573 
19576 /*---------------------------------------------------------------------------*/
19577 /* Static function prototypes */
19578 /*---------------------------------------------------------------------------*/
19579 
19580 static void ddRehashZdd (DdManager *unique, int i);
19581 static int ddResizeTable (DdManager *unique, int index, int amount);
19582 
19583 DD_INLINE static void ddFixLimits (DdManager *unique);
19584 #ifdef DD_RED_BLACK_FREE_LIST
19585 static void cuddOrderedInsert (DdNodePtr *root, DdNodePtr node);
19586 static DdNode * cuddOrderedThread (DdNode *root, DdNode *list);
19587 static void cuddRotateLeft (DdNodePtr *nodeP);
19588 static void cuddRotateRight (DdNodePtr *nodeP);
19589 static void cuddDoRebalance (DdNodePtr **stack, int stackN);
19590 #endif
19591 static void ddPatchTree (DdManager *dd, MtrNode *treenode);
19592 #ifdef DD_DEBUG
19593 static int cuddCheckCollisionOrdering (DdManager *unique, int i, int j);
19594 #endif
19595 static void ddReportRefMess (DdManager *unique, int i, const char *caller);
19596 
19600 /*---------------------------------------------------------------------------*/
19601 /* Definition of exported functions */
19602 /*---------------------------------------------------------------------------*/
19603 
19604 /*---------------------------------------------------------------------------*/
19605 /* Definition of internal functions */
19606 /*---------------------------------------------------------------------------*/
19607 
19608 
19623 DdNode *
19625 DdManager * unique)
19626 {
19627 int i;
19628 DdNodePtr *mem;
19629 DdNode *list, *node;
19630 extern DD_OOMFP MMoutOfMemory;
19631 DD_OOMFP saveHandler;
19632 
19633 if (unique->nextFree == NULL) { /* free list is empty */
19634 /* Check for exceeded limits. */
19635 if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) >
19636 unique->maxLive) {
19637 unique->errorCode = CUDD_TOO_MANY_NODES;
19638 return(NULL);
19639 }
19640 if (util_cpu_time() - unique->startTime > unique->timeLimit) {
19642 return(NULL);
19643 }
19644 if (unique->stash == NULL || unique->memused > unique->maxmemhard) {
19645 (void) cuddGarbageCollect(unique,1);
19646 mem = NULL;
19647 }
19648 if (unique->nextFree == NULL) {
19649 if (unique->memused > unique->maxmemhard) {
19651 return(NULL);
19652 }
19653 /* Try to allocate a new block. */
19654 saveHandler = MMoutOfMemory;
19655 MMoutOfMemory = Cudd_OutOfMem;
19656 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
19657 MMoutOfMemory = saveHandler;
19658 if (mem == NULL) {
19659 /* No more memory: Try collecting garbage. If this succeeds,
19660 ** we end up with mem still NULL, but unique->nextFree !=
19661 ** NULL. */
19662 if (cuddGarbageCollect(unique,1) == 0) {
19663 /* Last resort: Free the memory stashed away, if there
19664 ** any. If this succeeeds, mem != NULL and
19665 ** unique->nextFree still NULL. */
19666 if (unique->stash != NULL) {
19667 FREE(unique->stash);
19668 unique->stash = NULL;
19669 /* Inhibit resizing of tables. */
19670 cuddSlowTableGrowth(unique);
19671 /* Now try again. */
19672 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
19673 }
19674 if (mem == NULL) {
19675 /* Out of luck. Call the default handler to do
19676 ** whatever it specifies for a failed malloc.
19677 ** If this handler returns, then set error code,
19678 ** print warning, and return. */
19679 (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
19680 unique->errorCode = CUDD_MEMORY_OUT;
19681 #ifdef DD_VERBOSE
19682 (void) fprintf(unique->err,
19683 "cuddAllocNode: out of memory");
19684 (void) fprintf(unique->err, "Memory in use = %lu\n",
19685 unique->memused);
19686 #endif
19687 return(NULL);
19688 }
19689 }
19690 }
19691 if (mem != NULL) { /* successful allocation; slice memory */
19692 ptruint offset;
19693 unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
19694 mem[0] = (DdNodePtr) unique->memoryList;
19695 unique->memoryList = mem;
19696 
19697 /* Here we rely on the fact that a DdNode is as large
19698 ** as 4 pointers. */
19699 offset = (ptruint) mem & (sizeof(DdNode) - 1);
19700 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
19701 assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0);
19702 list = (DdNode *) mem;
19703 
19704 i = 1;
19705 do {
19706 list[i - 1].ref = 0;
19707 list[i - 1].next = &list[i];
19708 } while (++i < DD_MEM_CHUNK);
19709 
19710 list[DD_MEM_CHUNK-1].ref = 0;
19711 list[DD_MEM_CHUNK-1].next = NULL;
19712 
19713 unique->nextFree = &list[0];
19714 }
19715 }
19716 }
19717 unique->allocated++;
19718 node = unique->nextFree;
19719 unique->nextFree = node->next;
19720 return(node);
19721 
19722 } /* end of cuddAllocNode */
19723 
19724 
19737 DdManager *
19739 unsigned int numVars /* Initial number of BDD variables (and subtables) */,
19740 unsigned int numVarsZ /* Initial number of ZDD variables (and subtables) */,
19741 unsigned int numSlots /* Initial size of the BDD subtables */,
19742 unsigned int looseUpTo /* Limit for fast table growth */)
19743 {
19744 DdManager *unique = ALLOC(DdManager,1);
19745 int i, j;
19746 DdNodePtr *nodelist;
19747 DdNode *sentinel;
19748 unsigned int slots;
19749 int shift;
19750 
19751 if (unique == NULL) {
19752 return(NULL);
19753 }
19754 sentinel = &(unique->sentinel);
19755 sentinel->ref = 0;
19756 sentinel->index = 0;
19757 cuddT(sentinel) = NULL;
19758 cuddE(sentinel) = NULL;
19759 sentinel->next = NULL;
19760 unique->epsilon = DD_EPSILON;
19761 unique->size = numVars;
19762 unique->sizeZ = numVarsZ;
19763 unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars);
19764 unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ);
19765 
19766 /* Adjust the requested number of slots to a power of 2. */
19767 slots = 8;
19768 while (slots < numSlots) {
19769 slots <<= 1;
19770 }
19771 unique->initSlots = slots;
19772 shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots);
19773 
19774 unique->slots = (numVars + numVarsZ + 1) * slots;
19775 unique->keys = 0;
19776 unique->maxLive = ~0; /* very large number */
19777 unique->keysZ = 0;
19778 unique->dead = 0;
19779 unique->deadZ = 0;
19780 unique->gcFrac = DD_GC_FRAC_HI;
19781 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
19782 unique->looseUpTo = looseUpTo;
19783 unique->gcEnabled = 1;
19784 unique->allocated = 0;
19785 unique->reclaimed = 0;
19786 unique->subtables = ALLOC(DdSubtable,unique->maxSize);
19787 if (unique->subtables == NULL) {
19788 FREE(unique);
19789 return(NULL);
19790 }
19791 unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ);
19792 if (unique->subtableZ == NULL) {
19793 FREE(unique->subtables);
19794 FREE(unique);
19795 return(NULL);
19796 }
19797 unique->perm = ALLOC(int,unique->maxSize);
19798 if (unique->perm == NULL) {
19799 FREE(unique->subtables);
19800 FREE(unique->subtableZ);
19801 FREE(unique);
19802 return(NULL);
19803 }
19804 unique->invperm = ALLOC(int,unique->maxSize);
19805 if (unique->invperm == NULL) {
19806 FREE(unique->subtables);
19807 FREE(unique->subtableZ);
19808 FREE(unique->perm);
19809 FREE(unique);
19810 return(NULL);
19811 }
19812 unique->permZ = ALLOC(int,unique->maxSizeZ);
19813 if (unique->permZ == NULL) {
19814 FREE(unique->subtables);
19815 FREE(unique->subtableZ);
19816 FREE(unique->perm);
19817 FREE(unique->invperm);
19818 FREE(unique);
19819 return(NULL);
19820 }
19821 unique->invpermZ = ALLOC(int,unique->maxSizeZ);
19822 if (unique->invpermZ == NULL) {
19823 FREE(unique->subtables);
19824 FREE(unique->subtableZ);
19825 FREE(unique->perm);
19826 FREE(unique->invperm);
19827 FREE(unique->permZ);
19828 FREE(unique);
19829 return(NULL);
19830 }
19831 unique->map = NULL;
19832 unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1);
19833 if (unique->stack == NULL) {
19834 FREE(unique->subtables);
19835 FREE(unique->subtableZ);
19836 FREE(unique->perm);
19837 FREE(unique->invperm);
19838 FREE(unique->permZ);
19839 FREE(unique->invpermZ);
19840 FREE(unique);
19841 return(NULL);
19842 }
19843 unique->stack[0] = NULL; /* to suppress harmless UMR */
19844 
19845 #ifndef DD_NO_DEATH_ROW
19846 unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2);
19847 unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth);
19848 if (unique->deathRow == NULL) {
19849 FREE(unique->subtables);
19850 FREE(unique->subtableZ);
19851 FREE(unique->perm);
19852 FREE(unique->invperm);
19853 FREE(unique->permZ);
19854 FREE(unique->invpermZ);
19855 FREE(unique->stack);
19856 FREE(unique);
19857 return(NULL);
19858 }
19859 for (i = 0; i < unique->deathRowDepth; i++) {
19860 unique->deathRow[i] = NULL;
19861 }
19862 unique->nextDead = 0;
19863 unique->deadMask = unique->deathRowDepth - 1;
19864 #endif
19865 
19866 for (i = 0; (unsigned) i < numVars; i++) {
19867 unique->subtables[i].slots = slots;
19868 unique->subtables[i].shift = shift;
19869 unique->subtables[i].keys = 0;
19870 unique->subtables[i].dead = 0;
19871 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
19872 unique->subtables[i].bindVar = 0;
19874 unique->subtables[i].pairIndex = 0;
19875 unique->subtables[i].varHandled = 0;
19877 
19878 nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots);
19879 if (nodelist == NULL) {
19880 for (j = 0; j < i; j++) {
19881 FREE(unique->subtables[j].nodelist);
19882 }
19883 FREE(unique->subtables);
19884 FREE(unique->subtableZ);
19885 FREE(unique->perm);
19886 FREE(unique->invperm);
19887 FREE(unique->permZ);
19888 FREE(unique->invpermZ);
19889 FREE(unique->stack);
19890 FREE(unique);
19891 return(NULL);
19892 }
19893 for (j = 0; (unsigned) j < slots; j++) {
19894 nodelist[j] = sentinel;
19895 }
19896 unique->perm[i] = i;
19897 unique->invperm[i] = i;
19898 }
19899 for (i = 0; (unsigned) i < numVarsZ; i++) {
19900 unique->subtableZ[i].slots = slots;
19901 unique->subtableZ[i].shift = shift;
19902 unique->subtableZ[i].keys = 0;
19903 unique->subtableZ[i].dead = 0;
19904 unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
19905 nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots);
19906 if (nodelist == NULL) {
19907 for (j = 0; (unsigned) j < numVars; j++) {
19908 FREE(unique->subtables[j].nodelist);
19909 }
19910 FREE(unique->subtables);
19911 for (j = 0; j < i; j++) {
19912 FREE(unique->subtableZ[j].nodelist);
19913 }
19914 FREE(unique->subtableZ);
19915 FREE(unique->perm);
19916 FREE(unique->invperm);
19917 FREE(unique->permZ);
19918 FREE(unique->invpermZ);
19919 FREE(unique->stack);
19920 FREE(unique);
19921 return(NULL);
19922 }
19923 for (j = 0; (unsigned) j < slots; j++) {
19924 nodelist[j] = NULL;
19925 }
19926 unique->permZ[i] = i;
19927 unique->invpermZ[i] = i;
19928 }
19929 unique->constants.slots = slots;
19930 unique->constants.shift = shift;
19931 unique->constants.keys = 0;
19932 unique->constants.dead = 0;
19933 unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
19934 nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots);
19935 if (nodelist == NULL) {
19936 for (j = 0; (unsigned) j < numVars; j++) {
19937 FREE(unique->subtables[j].nodelist);
19938 }
19939 FREE(unique->subtables);
19940 for (j = 0; (unsigned) j < numVarsZ; j++) {
19941 FREE(unique->subtableZ[j].nodelist);
19942 }
19943 FREE(unique->subtableZ);
19944 FREE(unique->perm);
19945 FREE(unique->invperm);
19946 FREE(unique->permZ);
19947 FREE(unique->invpermZ);
19948 FREE(unique->stack);
19949 FREE(unique);
19950 return(NULL);
19951 }
19952 for (j = 0; (unsigned) j < slots; j++) {
19953 nodelist[j] = NULL;
19954 }
19955 
19956 unique->memoryList = NULL;
19957 unique->nextFree = NULL;
19958 
19959 unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ)
19960 * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) *
19961 slots * sizeof(DdNodePtr) +
19962 (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr);
19963 #ifndef DD_NO_DEATH_ROW
19964 unique->memused += unique->deathRowDepth * sizeof(DdNodePtr);
19965 #endif
19966 
19967 /* Initialize fields concerned with automatic dynamic reordering. */
19968 unique->reordered = 0;
19969 unique->reorderings = 0;
19970 unique->maxReorderings = ~0;
19971 unique->siftMaxVar = DD_SIFT_MAX_VAR;
19972 unique->siftMaxSwap = DD_SIFT_MAX_SWAPS;
19974 unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH;
19975 unique->reordCycle = 0; /* do not use alternate threshold */
19976 unique->autoDyn = 0; /* initially disabled */
19977 unique->autoDynZ = 0; /* initially disabled */
19978 unique->autoMethod = CUDD_REORDER_SIFT;
19979 unique->autoMethodZ = CUDD_REORDER_SIFT;
19980 unique->realign = 0; /* initially disabled */
19981 unique->realignZ = 0; /* initially disabled */
19982 unique->nextDyn = DD_FIRST_REORDER;
19983 unique->countDead = ~0;
19984 unique->tree = NULL;
19985 unique->treeZ = NULL;
19986 unique->groupcheck = CUDD_GROUP_CHECK7;
19987 unique->recomb = DD_DEFAULT_RECOMB;
19988 unique->symmviolation = 0;
19989 unique->arcviolation = 0;
19990 unique->populationSize = 0;
19991 unique->numberXovers = 0;
19992 unique->randomizeOrder = 0;
19993 unique->linear = NULL;
19994 unique->linearSize = 0;
19995 
19996 /* Initialize ZDD universe. */
19997 unique->univ = (DdNodePtr *)NULL;
19998 
19999 /* Initialize auxiliary fields. */
20000 unique->localCaches = NULL;
20001 unique->preGCHook = NULL;
20002 unique->postGCHook = NULL;
20003 unique->preReorderingHook = NULL;
20004 unique->postReorderingHook = NULL;
20005 unique->out = stdout;
20006 unique->err = stderr;
20007 unique->errorCode = CUDD_NO_ERROR;
20008 unique->startTime = util_cpu_time();
20009 unique->timeLimit = ~0UL;
20010 
20011 /* Initialize statistical counters. */
20012 unique->maxmemhard = ~ 0UL;
20013 unique->garbageCollections = 0;
20014 unique->GCTime = 0;
20015 unique->reordTime = 0;
20016 #ifdef DD_STATS
20017 unique->nodesDropped = 0;
20018 unique->nodesFreed = 0;
20019 #endif
20020 unique->peakLiveNodes = 0;
20021 #ifdef DD_UNIQUE_PROFILE
20022 unique->uniqueLookUps = 0;
20023 unique->uniqueLinks = 0;
20024 #endif
20025 #ifdef DD_COUNT
20026 unique->recursiveCalls = 0;
20027 unique->swapSteps = 0;
20028 #ifdef DD_STATS
20029 unique->nextSample = 250000;
20030 #endif
20031 #endif
20032 
20033 return(unique);
20034 
20035 } /* end of cuddInitTable */
20036 
20037 
20049 void
20051 DdManager * unique)
20052 {
20053 DdNodePtr *next;
20054 DdNodePtr *memlist = unique->memoryList;
20055 int i;
20056 
20057 if (unique->univ != NULL) cuddZddFreeUniv(unique);
20058 while (memlist != NULL) {
20059 next = (DdNodePtr *) memlist[0]; /* link to next block */
20060 FREE(memlist);
20061 memlist = next;
20062 }
20063 unique->nextFree = NULL;
20064 unique->memoryList = NULL;
20065 
20066 for (i = 0; i < unique->size; i++) {
20067 FREE(unique->subtables[i].nodelist);
20068 }
20069 for (i = 0; i < unique->sizeZ; i++) {
20070 FREE(unique->subtableZ[i].nodelist);
20071 }
20072 FREE(unique->constants.nodelist);
20073 FREE(unique->subtables);
20074 FREE(unique->subtableZ);
20075 FREE(unique->acache);
20076 FREE(unique->perm);
20077 FREE(unique->permZ);
20078 FREE(unique->invperm);
20079 FREE(unique->invpermZ);
20080 FREE(unique->vars);
20081 if (unique->map != NULL) FREE(unique->map);
20082 FREE(unique->stack);
20083 #ifndef DD_NO_DEATH_ROW
20084 FREE(unique->deathRow);
20085 #endif
20086 if (unique->tree != NULL) Mtr_FreeTree(unique->tree);
20087 if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ);
20088 if (unique->linear != NULL) FREE(unique->linear);
20089 while (unique->preGCHook != NULL)
20090 Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK);
20091 while (unique->postGCHook != NULL)
20093 while (unique->preReorderingHook != NULL)
20094 Cudd_RemoveHook(unique,unique->preReorderingHook->f,
20096 while (unique->postReorderingHook != NULL)
20097 Cudd_RemoveHook(unique,unique->postReorderingHook->f,
20099 FREE(unique);
20100 
20101 } /* end of cuddFreeTable */
20102 
20103 
20119 int
20121 DdManager * unique,
20122 int clearCache)
20123 {
20124 DdHook *hook;
20125 DdCache *cache = unique->cache;
20126 DdNode *sentinel = &(unique->sentinel);
20127 DdNodePtr *nodelist;
20128 int i, j, deleted, totalDeleted, totalDeletedZ;
20129 DdCache *c;
20130 DdNode *node,*next;
20131 DdNodePtr *lastP;
20132 int slots;
20133 unsigned long localTime;
20134 #ifndef DD_UNSORTED_FREE_LIST
20135 #ifdef DD_RED_BLACK_FREE_LIST
20136 DdNodePtr tree;
20137 #else
20138 DdNodePtr *memListTrav, *nxtNode;
20139 DdNode *downTrav, *sentry;
20140 int k;
20141 #endif
20142 #endif
20143 
20144 #ifndef DD_NO_DEATH_ROW
20145 cuddClearDeathRow(unique);
20146 #endif
20147 
20148 hook = unique->preGCHook;
20149 while (hook != NULL) {
20150 int res = (hook->f)(unique,"DD",NULL);
20151 if (res == 0) return(0);
20152 hook = hook->next;
20153 }
20154 
20155 if (unique->dead + unique->deadZ == 0) {
20156 hook = unique->postGCHook;
20157 while (hook != NULL) {
20158 int res = (hook->f)(unique,"DD",NULL);
20159 if (res == 0) return(0);
20160 hook = hook->next;
20161 }
20162 return(0);
20163 }
20164 
20165 /* If many nodes are being reclaimed, we want to resize the tables
20166 ** more aggressively, to reduce the frequency of garbage collection.
20167 */
20168 if (clearCache && unique->gcFrac == DD_GC_FRAC_LO &&
20169 unique->slots <= unique->looseUpTo && unique->stash != NULL) {
20170 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
20171 #ifdef DD_VERBOSE
20172 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI);
20173 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
20174 #endif
20175 unique->gcFrac = DD_GC_FRAC_HI;
20176 return(0);
20177 }
20178 
20179 localTime = util_cpu_time();
20180 
20181 unique->garbageCollections++;
20182 #ifdef DD_VERBOSE
20183 (void) fprintf(unique->err,
20184 "garbage collecting (%d dead BDD nodes out of %d, min %d)...",
20185 unique->dead, unique->keys, unique->minDead);
20186 (void) fprintf(unique->err,
20187 " (%d dead ZDD nodes out of %d)...",
20188 unique->deadZ, unique->keysZ);
20189 #endif
20190 
20191 /* Remove references to garbage collected nodes from the cache. */
20192 if (clearCache) {
20193 slots = unique->cacheSlots;
20194 for (i = 0; i < slots; i++) {
20195 c = &cache[i];
20196 if (c->data != NULL) {
20197 if (cuddClean(c->f)->ref == 0 ||
20198 cuddClean(c->g)->ref == 0 ||
20199 (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) ||
20200 (c->data != DD_NON_CONSTANT &&
20201 Cudd_Regular(c->data)->ref == 0)) {
20202 c->data = NULL;
20203 unique->cachedeletions++;
20204 }
20205 }
20206 }
20207 cuddLocalCacheClearDead(unique);
20208 }
20209 
20210 /* Now return dead nodes to free list. Count them for sanity check. */
20211 totalDeleted = 0;
20212 #ifndef DD_UNSORTED_FREE_LIST
20213 #ifdef DD_RED_BLACK_FREE_LIST
20214 tree = NULL;
20215 #endif
20216 #endif
20217 
20218 for (i = 0; i < unique->size; i++) {
20219 if (unique->subtables[i].dead == 0) continue;
20220 nodelist = unique->subtables[i].nodelist;
20221 
20222 deleted = 0;
20223 slots = unique->subtables[i].slots;
20224 for (j = 0; j < slots; j++) {
20225 lastP = &(nodelist[j]);
20226 node = *lastP;
20227 while (node != sentinel) {
20228 next = node->next;
20229 if (node->ref == 0) {
20230 deleted++;
20231 #ifndef DD_UNSORTED_FREE_LIST
20232 #ifdef DD_RED_BLACK_FREE_LIST
20233 cuddOrderedInsert(&tree,node);
20234 #endif
20235 #else
20236 cuddDeallocNode(unique,node);
20237 #endif
20238 } else {
20239 *lastP = node;
20240 lastP = &(node->next);
20241 }
20242 node = next;
20243 }
20244 *lastP = sentinel;
20245 }
20246 if ((unsigned) deleted != unique->subtables[i].dead) {
20247 ddReportRefMess(unique, i, "cuddGarbageCollect");
20248 }
20249 totalDeleted += deleted;
20250 unique->subtables[i].keys -= deleted;
20251 unique->subtables[i].dead = 0;
20252 }
20253 if (unique->constants.dead != 0) {
20254 nodelist = unique->constants.nodelist;
20255 deleted = 0;
20256 slots = unique->constants.slots;
20257 for (j = 0; j < slots; j++) {
20258 lastP = &(nodelist[j]);
20259 node = *lastP;
20260 while (node != NULL) {
20261 next = node->next;
20262 if (node->ref == 0) {
20263 deleted++;
20264 #ifndef DD_UNSORTED_FREE_LIST
20265 #ifdef DD_RED_BLACK_FREE_LIST
20266 cuddOrderedInsert(&tree,node);
20267 #endif
20268 #else
20269 cuddDeallocNode(unique,node);
20270 #endif
20271 } else {
20272 *lastP = node;
20273 lastP = &(node->next);
20274 }
20275 node = next;
20276 }
20277 *lastP = NULL;
20278 }
20279 if ((unsigned) deleted != unique->constants.dead) {
20280 ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect");
20281 }
20282 totalDeleted += deleted;
20283 unique->constants.keys -= deleted;
20284 unique->constants.dead = 0;
20285 }
20286 if ((unsigned) totalDeleted != unique->dead) {
20287 ddReportRefMess(unique, -1, "cuddGarbageCollect");
20288 }
20289 unique->keys -= totalDeleted;
20290 unique->dead = 0;
20291 #ifdef DD_STATS
20292 unique->nodesFreed += (double) totalDeleted;
20293 #endif
20294 
20295 totalDeletedZ = 0;
20296 
20297 for (i = 0; i < unique->sizeZ; i++) {
20298 if (unique->subtableZ[i].dead == 0) continue;
20299 nodelist = unique->subtableZ[i].nodelist;
20300 
20301 deleted = 0;
20302 slots = unique->subtableZ[i].slots;
20303 for (j = 0; j < slots; j++) {
20304 lastP = &(nodelist[j]);
20305 node = *lastP;
20306 while (node != NULL) {
20307 next = node->next;
20308 if (node->ref == 0) {
20309 deleted++;
20310 #ifndef DD_UNSORTED_FREE_LIST
20311 #ifdef DD_RED_BLACK_FREE_LIST
20312 cuddOrderedInsert(&tree,node);
20313 #endif
20314 #else
20315 cuddDeallocNode(unique,node);
20316 #endif
20317 } else {
20318 *lastP = node;
20319 lastP = &(node->next);
20320 }
20321 node = next;
20322 }
20323 *lastP = NULL;
20324 }
20325 if ((unsigned) deleted != unique->subtableZ[i].dead) {
20326 ddReportRefMess(unique, i, "cuddGarbageCollect");
20327 }
20328 totalDeletedZ += deleted;
20329 unique->subtableZ[i].keys -= deleted;
20330 unique->subtableZ[i].dead = 0;
20331 }
20332 
20333 /* No need to examine the constant table for ZDDs.
20334 ** If we did we should be careful not to count whatever dead
20335 ** nodes we found there among the dead ZDD nodes. */
20336 if ((unsigned) totalDeletedZ != unique->deadZ) {
20337 ddReportRefMess(unique, -1, "cuddGarbageCollect");
20338 }
20339 unique->keysZ -= totalDeletedZ;
20340 unique->deadZ = 0;
20341 #ifdef DD_STATS
20342 unique->nodesFreed += (double) totalDeletedZ;
20343 #endif
20344 
20345 
20346 #ifndef DD_UNSORTED_FREE_LIST
20347 #ifdef DD_RED_BLACK_FREE_LIST
20348 unique->nextFree = cuddOrderedThread(tree,unique->nextFree);
20349 #else
20350 memListTrav = unique->memoryList;
20351 sentry = NULL;
20352 while (memListTrav != NULL) {
20353 ptruint offset;
20354 nxtNode = (DdNodePtr *)memListTrav[0];
20355 offset = (ptruint) memListTrav & (sizeof(DdNode) - 1);
20356 memListTrav += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
20357 downTrav = (DdNode *)memListTrav;
20358 k = 0;
20359 do {
20360 if (downTrav[k].ref == 0) {
20361 if (sentry == NULL) {
20362 unique->nextFree = sentry = &downTrav[k];
20363 } else {
20364 /* First hook sentry->next to the dead node and then
20365 ** reassign sentry to the dead node. */
20366 sentry = (sentry->next = &downTrav[k]);
20367 }
20368 }
20369 } while (++k < DD_MEM_CHUNK);
20370 memListTrav = nxtNode;
20371 }
20372 sentry->next = NULL;
20373 #endif
20374 #endif
20375 
20376 unique->GCTime += util_cpu_time() - localTime;
20377 
20378 hook = unique->postGCHook;
20379 while (hook != NULL) {
20380 int res = (hook->f)(unique,"DD",NULL);
20381 if (res == 0) return(0);
20382 hook = hook->next;
20383 }
20384 
20385 #ifdef DD_VERBOSE
20386 (void) fprintf(unique->err," done\n");
20387 #endif
20388 
20389 return(totalDeleted+totalDeletedZ);
20390 
20391 } /* end of cuddGarbageCollect */
20392 
20393 
20407 DdNode *
20409 DdManager * zdd,
20410 int id,
20411 DdNode * T,
20412 DdNode * E)
20413 {
20414 DdNode *node;
20415 
20416 if (T == DD_ZERO(zdd))
20417 return(E);
20418 node = cuddUniqueInterZdd(zdd, id, T, E);
20419 return(node);
20420 
20421 } /* end of cuddZddGetNode */
20422 
20423 
20440 DdNode *
20442 DdManager * dd,
20443 int index,
20444 DdNode * g,
20445 DdNode * h)
20446 {
20447 DdNode *f, *r, *t;
20448 DdNode *zdd_one = DD_ONE(dd);
20449 DdNode *zdd_zero = DD_ZERO(dd);
20450 
20451 f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero);
20452 if (f == NULL) {
20453 return(NULL);
20454 }
20455 cuddRef(f);
20456 t = cuddZddProduct(dd, f, g);
20457 if (t == NULL) {
20458 Cudd_RecursiveDerefZdd(dd, f);
20459 return(NULL);
20460 }
20461 cuddRef(t);
20462 Cudd_RecursiveDerefZdd(dd, f);
20463 r = cuddZddUnion(dd, t, h);
20464 if (r == NULL) {
20465 Cudd_RecursiveDerefZdd(dd, t);
20466 return(NULL);
20467 }
20468 cuddRef(r);
20469 Cudd_RecursiveDerefZdd(dd, t);
20470 
20471 cuddDeref(r);
20472 return(r);
20473 
20474 } /* end of cuddZddGetNodeIVO */
20475 
20476 
20494 DdNode *
20496 DdManager * unique,
20497 int index,
20498 DdNode * T,
20499 DdNode * E)
20500 {
20501 int pos;
20502 unsigned int level;
20503 int retval;
20504 DdNodePtr *nodelist;
20505 DdNode *looking;
20506 DdNodePtr *previousP;
20507 DdSubtable *subtable;
20508 int gcNumber;
20509 
20510 #ifdef DD_UNIQUE_PROFILE
20511 unique->uniqueLookUps++;
20512 #endif
20513 
20514 if ((0x1ffffUL & (unsigned long) unique->cacheMisses) == 0) {
20515 if (util_cpu_time() - unique->startTime > unique->timeLimit) {
20517 return(NULL);
20518 }
20519 }
20520 if (index >= unique->size) {
20521 int amount = ddMax(DD_DEFAULT_RESIZE,unique->size/20);
20522 if (!ddResizeTable(unique,index,amount)) return(NULL);
20523 }
20524 
20525 level = unique->perm[index];
20526 subtable = &(unique->subtables[level]);
20527 
20528 #ifdef DD_DEBUG
20529 assert(level < (unsigned) cuddI(unique,T->index));
20530 assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
20531 #endif
20532 
20533 pos = ddHash(T, E, subtable->shift);
20534 nodelist = subtable->nodelist;
20535 previousP = &(nodelist[pos]);
20536 looking = *previousP;
20537 
20538 while (T < cuddT(looking)) {
20539 previousP = &(looking->next);
20540 looking = *previousP;
20541 #ifdef DD_UNIQUE_PROFILE
20542 unique->uniqueLinks++;
20543 #endif
20544 }
20545 while (T == cuddT(looking) && E < cuddE(looking)) {
20546 previousP = &(looking->next);
20547 looking = *previousP;
20548 #ifdef DD_UNIQUE_PROFILE
20549 unique->uniqueLinks++;
20550 #endif
20551 }
20552 if (T == cuddT(looking) && E == cuddE(looking)) {
20553 if (looking->ref == 0) {
20554 cuddReclaim(unique,looking);
20555 }
20556 return(looking);
20557 }
20558 
20559 /* countDead is 0 if deads should be counted and ~0 if they should not. */
20560 if (unique->autoDyn &&
20561 unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn &&
20562 unique->maxReorderings > 0) {
20563 unsigned long cpuTime;
20564 #ifdef DD_DEBUG
20565 retval = Cudd_DebugCheck(unique);
20566 if (retval != 0) return(NULL);
20567 retval = Cudd_CheckKeys(unique);
20568 if (retval != 0) return(NULL);
20569 #endif
20570 retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */
20571 unique->maxReorderings--;
20572 if (retval == 0) {
20573 unique->reordered = 2;
20574 } else if ((cpuTime = util_cpu_time()) - unique->startTime > unique->timeLimit) {
20576 unique->reordered = 0;
20577 } else if (unique->timeLimit - (cpuTime - unique->startTime)
20578 < unique->reordTime) {
20579 unique->autoDyn = 0;
20580 }
20581 #ifdef DD_DEBUG
20582 retval = Cudd_DebugCheck(unique);
20583 if (retval != 0) unique->reordered = 2;
20584 retval = Cudd_CheckKeys(unique);
20585 if (retval != 0) unique->reordered = 2;
20586 #endif
20587 return(NULL);
20588 }
20589 
20590 if (subtable->keys > subtable->maxKeys) {
20591 if (unique->gcEnabled &&
20592 ((unique->dead > unique->minDead) ||
20593 ((unique->dead > unique->minDead / 2) &&
20594 (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */
20595 if (util_cpu_time() - unique->startTime > unique->timeLimit) {
20597 return(NULL);
20598 }
20599 (void) cuddGarbageCollect(unique,1);
20600 } else {
20601 cuddRehash(unique,(int)level);
20602 }
20603 /* Update pointer to insertion point. In the case of rehashing,
20604 ** the slot may have changed. In the case of garbage collection,
20605 ** the predecessor may have been dead. */
20606 pos = ddHash(T, E, subtable->shift);
20607 nodelist = subtable->nodelist;
20608 previousP = &(nodelist[pos]);
20609 looking = *previousP;
20610 
20611 while (T < cuddT(looking)) {
20612 previousP = &(looking->next);
20613 looking = *previousP;
20614 #ifdef DD_UNIQUE_PROFILE
20615 unique->uniqueLinks++;
20616 #endif
20617 }
20618 while (T == cuddT(looking) && E < cuddE(looking)) {
20619 previousP = &(looking->next);
20620 looking = *previousP;
20621 #ifdef DD_UNIQUE_PROFILE
20622 unique->uniqueLinks++;
20623 #endif
20624 }
20625 }
20626 
20627 gcNumber = unique->garbageCollections;
20628 looking = cuddAllocNode(unique);
20629 if (looking == NULL) {
20630 return(NULL);
20631 }
20632 unique->keys++;
20633 subtable->keys++;
20634 
20635 if (gcNumber != unique->garbageCollections) {
20636 DdNode *looking2;
20637 pos = ddHash(T, E, subtable->shift);
20638 nodelist = subtable->nodelist;
20639 previousP = &(nodelist[pos]);
20640 looking2 = *previousP;
20641 
20642 while (T < cuddT(looking2)) {
20643 previousP = &(looking2->next);
20644 looking2 = *previousP;
20645 #ifdef DD_UNIQUE_PROFILE
20646 unique->uniqueLinks++;
20647 #endif
20648 }
20649 while (T == cuddT(looking2) && E < cuddE(looking2)) {
20650 previousP = &(looking2->next);
20651 looking2 = *previousP;
20652 #ifdef DD_UNIQUE_PROFILE
20653 unique->uniqueLinks++;
20654 #endif
20655 }
20656 }
20657 looking->index = index;
20658 cuddT(looking) = T;
20659 cuddE(looking) = E;
20660 looking->next = *previousP;
20661 *previousP = looking;
20662 cuddSatInc(T->ref); /* we know T is a regular pointer */
20663 cuddRef(E);
20664 
20665 #ifdef DD_DEBUG
20666 cuddCheckCollisionOrdering(unique,level,pos);
20667 #endif
20668 
20669 return(looking);
20670 
20671 } /* end of cuddUniqueInter */
20672 
20673 
20690 DdNode *
20692 DdManager * unique,
20693 int index,
20694 DdNode * T,
20695 DdNode * E)
20696 {
20697 DdNode *result;
20698 DdNode *v;
20699 
20700 v = cuddUniqueInter(unique, index, DD_ONE(unique),
20701 Cudd_Not(DD_ONE(unique)));
20702 if (v == NULL)
20703 return(NULL);
20704 /* Since v is a projection function, we can skip the call to cuddRef. */
20705 result = cuddBddIteRecur(unique, v, T, E);
20706 return(result);
20707 
20708 } /* end of cuddUniqueInterIVO */
20709 
20710 
20729 DdNode *
20731 DdManager * unique,
20732 int index,
20733 DdNode * T,
20734 DdNode * E)
20735 {
20736 int pos;
20737 unsigned int level;
20738 int retval;
20739 DdNodePtr *nodelist;
20740 DdNode *looking;
20741 DdSubtable *subtable;
20742 
20743 #ifdef DD_UNIQUE_PROFILE
20744 unique->uniqueLookUps++;
20745 #endif
20746 
20747 if (index >= unique->sizeZ) {
20748 if (!cuddResizeTableZdd(unique,index)) return(NULL);
20749 }
20750 
20751 level = unique->permZ[index];
20752 subtable = &(unique->subtableZ[level]);
20753 
20754 #ifdef DD_DEBUG
20755 assert(level < (unsigned) cuddIZ(unique,T->index));
20756 assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index));
20757 #endif
20758 
20759 if (subtable->keys > subtable->maxKeys) {
20760 if (unique->gcEnabled && ((unique->deadZ > unique->minDead) ||
20761 (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */
20762 (void) cuddGarbageCollect(unique,1);
20763 } else {
20764 ddRehashZdd(unique,(int)level);
20765 }
20766 }
20767 
20768 pos = ddHash(T, E, subtable->shift);
20769 nodelist = subtable->nodelist;
20770 looking = nodelist[pos];
20771 
20772 while (looking != NULL) {
20773 if (cuddT(looking) == T && cuddE(looking) == E) {
20774 if (looking->ref == 0) {
20775 cuddReclaimZdd(unique,looking);
20776 }
20777 return(looking);
20778 }
20779 looking = looking->next;
20780 #ifdef DD_UNIQUE_PROFILE
20781 unique->uniqueLinks++;
20782 #endif
20783 }
20784 
20785 /* countDead is 0 if deads should be counted and ~0 if they should not. */
20786 if (unique->autoDynZ &&
20787 unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) {
20788 #ifdef DD_DEBUG
20789 retval = Cudd_DebugCheck(unique);
20790 if (retval != 0) return(NULL);
20791 retval = Cudd_CheckKeys(unique);
20792 if (retval != 0) return(NULL);
20793 #endif
20794 retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */
20795 if (retval == 0) unique->reordered = 2;
20796 #ifdef DD_DEBUG
20797 retval = Cudd_DebugCheck(unique);
20798 if (retval != 0) unique->reordered = 2;
20799 retval = Cudd_CheckKeys(unique);
20800 if (retval != 0) unique->reordered = 2;
20801 #endif
20802 return(NULL);
20803 }
20804 
20805 unique->keysZ++;
20806 subtable->keys++;
20807 
20808 looking = cuddAllocNode(unique);
20809 if (looking == NULL) return(NULL);
20810 looking->index = index;
20811 cuddT(looking) = T;
20812 cuddE(looking) = E;
20813 looking->next = nodelist[pos];
20814 nodelist[pos] = looking;
20815 cuddRef(T);
20816 cuddRef(E);
20817 
20818 return(looking);
20819 
20820 } /* end of cuddUniqueInterZdd */
20821 
20822 
20836 DdNode *
20838 DdManager * unique,
20839 CUDD_VALUE_TYPE value)
20840 {
20841 int pos;
20842 DdNodePtr *nodelist;
20843 DdNode *looking;
20844 hack split;
20845 
20846 #ifdef DD_UNIQUE_PROFILE
20847 unique->uniqueLookUps++;
20848 #endif
20849 
20850 if (unique->constants.keys > unique->constants.maxKeys) {
20851 if (unique->gcEnabled && ((unique->dead > unique->minDead) ||
20852 (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */
20853 (void) cuddGarbageCollect(unique,1);
20854 } else {
20856 }
20857 }
20858 
20859 cuddAdjust(value); /* for the case of crippled infinities */
20860 
20861 if (ddAbs(value) < unique->epsilon) {
20862 value = 0.0;
20863 }
20864 split.value = value;
20865 
20866 pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift);
20867 nodelist = unique->constants.nodelist;
20868 looking = nodelist[pos];
20869 
20870 /* Here we compare values both for equality and for difference less
20871  * than epsilon. The first comparison is required when values are
20872  * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for
20873  * every X.
20874  */
20875 while (looking != NULL) {
20876 if (looking->type.value == value ||
20877 ddEqualVal(looking->type.value,value,unique->epsilon)) {
20878 if (looking->ref == 0) {
20879 cuddReclaim(unique,looking);
20880 }
20881 return(looking);
20882 }
20883 looking = looking->next;
20884 #ifdef DD_UNIQUE_PROFILE
20885 unique->uniqueLinks++;
20886 #endif
20887 }
20888 
20889 unique->keys++;
20890 unique->constants.keys++;
20891 
20892 looking = cuddAllocNode(unique);
20893 if (looking == NULL) return(NULL);
20894 looking->index = CUDD_CONST_INDEX;
20895 looking->type.value = value;
20896 looking->next = nodelist[pos];
20897 nodelist[pos] = looking;
20898 
20899 return(looking);
20900 
20901 } /* end of cuddUniqueConst */
20902 
20903 
20916 void
20918 DdManager * unique,
20919 int i)
20920 {
20921 unsigned int slots, oldslots;
20922 int shift, oldshift;
20923 int j, pos;
20924 DdNodePtr *nodelist, *oldnodelist;
20925 DdNode *node, *next;
20926 DdNode *sentinel = &(unique->sentinel);
20927 hack split;
20928 extern DD_OOMFP MMoutOfMemory;
20929 DD_OOMFP saveHandler;
20930 
20931 if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) {
20932 unique->gcFrac = DD_GC_FRAC_LO;
20933 unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
20934 #ifdef DD_VERBOSE
20935 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO);
20936 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
20937 #endif
20938 }
20939 
20940 if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) {
20941 unique->gcFrac = DD_GC_FRAC_MIN;
20942 unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
20943 #ifdef DD_VERBOSE
20944 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN);
20945 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
20946 #endif
20947 cuddShrinkDeathRow(unique);
20948 if (cuddGarbageCollect(unique,1) > 0) return;
20949 }
20950 
20951 if (i != CUDD_CONST_INDEX) {
20952 oldslots = unique->subtables[i].slots;
20953 oldshift = unique->subtables[i].shift;
20954 oldnodelist = unique->subtables[i].nodelist;
20955 
20956 /* Compute the new size of the subtable. */
20957 slots = oldslots << 1;
20958 shift = oldshift - 1;
20959 
20960 saveHandler = MMoutOfMemory;
20961 MMoutOfMemory = Cudd_OutOfMem;
20962 nodelist = ALLOC(DdNodePtr, slots);
20963 MMoutOfMemory = saveHandler;
20964 if (nodelist == NULL) {
20965 (void) fprintf(unique->err,
20966 "Unable to resize subtable %d for lack of memory\n",
20967 i);
20968 /* Prevent frequent resizing attempts. */
20969 (void) cuddGarbageCollect(unique,1);
20970 if (unique->stash != NULL) {
20971 FREE(unique->stash);
20972 unique->stash = NULL;
20973 /* Inhibit resizing of tables. */
20974 cuddSlowTableGrowth(unique);
20975 }
20976 return;
20977 }
20978 unique->subtables[i].nodelist = nodelist;
20979 unique->subtables[i].slots = slots;
20980 unique->subtables[i].shift = shift;
20981 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
20982 
20983 /* Move the nodes from the old table to the new table.
20984 ** This code depends on the type of hash function.
20985 ** It assumes that the effect of doubling the size of the table
20986 ** is to retain one more bit of the 32-bit hash value.
20987 ** The additional bit is the LSB. */
20988 for (j = 0; (unsigned) j < oldslots; j++) {
20989 DdNodePtr *evenP, *oddP;
20990 node = oldnodelist[j];
20991 evenP = &(nodelist[j<<1]);
20992 oddP = &(nodelist[(j<<1)+1]);
20993 while (node != sentinel) {
20994 next = node->next;
20995 pos = ddHash(cuddT(node), cuddE(node), shift);
20996 if (pos & 1) {
20997 *oddP = node;
20998 oddP = &(node->next);
20999 } else {
21000 *evenP = node;
21001 evenP = &(node->next);
21002 }
21003 node = next;
21004 }
21005 *evenP = *oddP = sentinel;
21006 }
21007 FREE(oldnodelist);
21008 
21009 #ifdef DD_VERBOSE
21010 (void) fprintf(unique->err,
21011 "rehashing layer %d: keys %d dead %d new size %d\n",
21012 i, unique->subtables[i].keys,
21013 unique->subtables[i].dead, slots);
21014 #endif
21015 } else {
21016 oldslots = unique->constants.slots;
21017 oldshift = unique->constants.shift;
21018 oldnodelist = unique->constants.nodelist;
21019 
21020 /* The constant subtable is never subjected to reordering.
21021 ** Therefore, when it is resized, it is because it has just
21022 ** reached the maximum load. We can safely just double the size,
21023 ** with no need for the loop we use for the other tables.
21024 */
21025 slots = oldslots << 1;
21026 shift = oldshift - 1;
21027 saveHandler = MMoutOfMemory;
21028 MMoutOfMemory = Cudd_OutOfMem;
21029 nodelist = ALLOC(DdNodePtr, slots);
21030 MMoutOfMemory = saveHandler;
21031 if (nodelist == NULL) {
21032 (void) fprintf(unique->err,
21033 "Unable to resize constant subtable for lack of memory\n");
21034 (void) cuddGarbageCollect(unique,1);
21035 for (j = 0; j < unique->size; j++) {
21036 unique->subtables[j].maxKeys <<= 1;
21037 }
21038 unique->constants.maxKeys <<= 1;
21039 return;
21040 }
21041 unique->constants.slots = slots;
21042 unique->constants.shift = shift;
21043 unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
21044 unique->constants.nodelist = nodelist;
21045 for (j = 0; (unsigned) j < slots; j++) {
21046 nodelist[j] = NULL;
21047 }
21048 for (j = 0; (unsigned) j < oldslots; j++) {
21049 node = oldnodelist[j];
21050 while (node != NULL) {
21051 next = node->next;
21052 split.value = cuddV(node);
21053 pos = ddHash(split.bits[0], split.bits[1], shift);
21054 node->next = nodelist[pos];
21055 nodelist[pos] = node;
21056 node = next;
21057 }
21058 }
21059 FREE(oldnodelist);
21060 
21061 #ifdef DD_VERBOSE
21062 (void) fprintf(unique->err,
21063 "rehashing constants: keys %d dead %d new size %d\n",
21064 unique->constants.keys,unique->constants.dead,slots);
21065 #endif
21066 }
21067 
21068 /* Update global data */
21069 
21070 unique->memused += (slots - oldslots) * sizeof(DdNodePtr);
21071 unique->slots += (slots - oldslots);
21072 ddFixLimits(unique);
21073 
21074 } /* end of cuddRehash */
21075 
21092 int
21094 DdManager * unique,
21095 int index)
21096 {
21097 DdSubtable *newsubtables;
21098 DdNodePtr *newnodelist;
21099 int oldsize,newsize;
21100 int i,j,reorderSave;
21101 unsigned int numSlots = unique->initSlots;
21102 int *newperm, *newinvperm;
21103 
21104 oldsize = unique->sizeZ;
21105 /* Easy case: there is still room in the current table. */
21106 if (index < unique->maxSizeZ) {
21107 for (i = oldsize; i <= index; i++) {
21108 unique->subtableZ[i].slots = numSlots;
21109 unique->subtableZ[i].shift = sizeof(int) * 8 -
21110 cuddComputeFloorLog2(numSlots);
21111 unique->subtableZ[i].keys = 0;
21112 unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
21113 unique->subtableZ[i].dead = 0;
21114 unique->permZ[i] = i;
21115 unique->invpermZ[i] = i;
21116 newnodelist = unique->subtableZ[i].nodelist =
21117 ALLOC(DdNodePtr, numSlots);
21118 if (newnodelist == NULL) {
21119 unique->errorCode = CUDD_MEMORY_OUT;
21120 return(0);
21121 }
21122 for (j = 0; (unsigned) j < numSlots; j++) {
21123 newnodelist[j] = NULL;
21124 }
21125 }
21126 } else {
21127 /* The current table is too small: we need to allocate a new,
21128 ** larger one; move all old subtables, and initialize the new
21129 ** subtables up to index included.
21130 */
21131 newsize = index + DD_DEFAULT_RESIZE;
21132 #ifdef DD_VERBOSE
21133 (void) fprintf(unique->err,
21134 "Increasing the ZDD table size from %d to %d\n",
21135 unique->maxSizeZ, newsize);
21136 #endif
21137 newsubtables = ALLOC(DdSubtable,newsize);
21138 if (newsubtables == NULL) {
21139 unique->errorCode = CUDD_MEMORY_OUT;
21140 return(0);
21141 }
21142 newperm = ALLOC(int,newsize);
21143 if (newperm == NULL) {
21144 unique->errorCode = CUDD_MEMORY_OUT;
21145 return(0);
21146 }
21147 newinvperm = ALLOC(int,newsize);
21148 if (newinvperm == NULL) {
21149 unique->errorCode = CUDD_MEMORY_OUT;
21150 return(0);
21151 }
21152 unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) *
21153 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
21154 if (newsize > unique->maxSize) {
21155 FREE(unique->stack);
21156 unique->stack = ALLOC(DdNodePtr,newsize + 1);
21157 if (unique->stack == NULL) {
21158 unique->errorCode = CUDD_MEMORY_OUT;
21159 return(0);
21160 }
21161 unique->stack[0] = NULL; /* to suppress harmless UMR */
21162 unique->memused +=
21163 (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
21164 * sizeof(DdNode *);
21165 }
21166 for (i = 0; i < oldsize; i++) {
21167 newsubtables[i].slots = unique->subtableZ[i].slots;
21168 newsubtables[i].shift = unique->subtableZ[i].shift;
21169 newsubtables[i].keys = unique->subtableZ[i].keys;
21170 newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys;
21171 newsubtables[i].dead = unique->subtableZ[i].dead;
21172 newsubtables[i].nodelist = unique->subtableZ[i].nodelist;
21173 newperm[i] = unique->permZ[i];
21174 newinvperm[i] = unique->invpermZ[i];
21175 }
21176 for (i = oldsize; i <= index; i++) {
21177 newsubtables[i].slots = numSlots;
21178 newsubtables[i].shift = sizeof(int) * 8 -
21179 cuddComputeFloorLog2(numSlots);
21180 newsubtables[i].keys = 0;
21181 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
21182 newsubtables[i].dead = 0;
21183 newperm[i] = i;
21184 newinvperm[i] = i;
21185 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
21186 if (newnodelist == NULL) {
21187 unique->errorCode = CUDD_MEMORY_OUT;
21188 return(0);
21189 }
21190 for (j = 0; (unsigned) j < numSlots; j++) {
21191 newnodelist[j] = NULL;
21192 }
21193 }
21194 FREE(unique->subtableZ);
21195 unique->subtableZ = newsubtables;
21196 unique->maxSizeZ = newsize;
21197 FREE(unique->permZ);
21198 unique->permZ = newperm;
21199 FREE(unique->invpermZ);
21200 unique->invpermZ = newinvperm;
21201 }
21202 unique->slots += (index + 1 - unique->sizeZ) * numSlots;
21203 ddFixLimits(unique);
21204 unique->sizeZ = index + 1;
21205 
21206 /* Now that the table is in a coherent state, update the ZDD
21207 ** universe. We need to temporarily disable reordering,
21208 ** because we cannot reorder without universe in place.
21209 */
21210 
21211 reorderSave = unique->autoDynZ;
21212 unique->autoDynZ = 0;
21213 cuddZddFreeUniv(unique);
21214 if (!cuddZddInitUniv(unique)) {
21215 unique->autoDynZ = reorderSave;
21216 return(0);
21217 }
21218 unique->autoDynZ = reorderSave;
21219 
21220 return(1);
21221 
21222 } /* end of cuddResizeTableZdd */
21223 
21224 
21236 void
21238 DdManager *unique)
21239 {
21240 int i;
21241 
21242 unique->maxCacheHard = unique->cacheSlots - 1;
21243 unique->cacheSlack = - (int) (unique->cacheSlots + 1);
21244 for (i = 0; i < unique->size; i++) {
21245 unique->subtables[i].maxKeys <<= 2;
21246 }
21247 unique->gcFrac = DD_GC_FRAC_MIN;
21248 unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
21249 cuddShrinkDeathRow(unique);
21250 (void) fprintf(unique->err,"Slowing down table growth: ");
21251 (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac);
21252 (void) fprintf(unique->err,"minDead = %u\n", unique->minDead);
21253 
21254 } /* end of cuddSlowTableGrowth */
21255 
21256 
21257 /*---------------------------------------------------------------------------*/
21258 /* Definition of static functions */
21259 /*---------------------------------------------------------------------------*/
21260 
21261 
21273 static void
21275 DdManager * unique,
21276 int i)
21277 {
21278 unsigned int slots, oldslots;
21279 int shift, oldshift;
21280 int j, pos;
21281 DdNodePtr *nodelist, *oldnodelist;
21282 DdNode *node, *next;
21283 extern DD_OOMFP MMoutOfMemory;
21284 DD_OOMFP saveHandler;
21285 
21286 if (unique->slots > unique->looseUpTo) {
21287 unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
21288 #ifdef DD_VERBOSE
21289 if (unique->gcFrac == DD_GC_FRAC_HI) {
21290 (void) fprintf(unique->err,"GC fraction = %.2f\t",
21291 DD_GC_FRAC_LO);
21292 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
21293 }
21294 #endif
21295 unique->gcFrac = DD_GC_FRAC_LO;
21296 }
21297 
21298 assert(i != CUDD_MAXINDEX);
21299 oldslots = unique->subtableZ[i].slots;
21300 oldshift = unique->subtableZ[i].shift;
21301 oldnodelist = unique->subtableZ[i].nodelist;
21302 
21303 /* Compute the new size of the subtable. Normally, we just
21304 ** double. However, after reordering, a table may be severely
21305 ** overloaded. Therefore, we iterate. */
21306 slots = oldslots;
21307 shift = oldshift;
21308 do {
21309 slots <<= 1;
21310 shift--;
21311 } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys);
21312 
21313 saveHandler = MMoutOfMemory;
21314 MMoutOfMemory = Cudd_OutOfMem;
21315 nodelist = ALLOC(DdNodePtr, slots);
21316 MMoutOfMemory = saveHandler;
21317 if (nodelist == NULL) {
21318 (void) fprintf(unique->err,
21319 "Unable to resize ZDD subtable %d for lack of memory.\n",
21320 i);
21321 (void) cuddGarbageCollect(unique,1);
21322 for (j = 0; j < unique->sizeZ; j++) {
21323 unique->subtableZ[j].maxKeys <<= 1;
21324 }
21325 return;
21326 }
21327 unique->subtableZ[i].nodelist = nodelist;
21328 unique->subtableZ[i].slots = slots;
21329 unique->subtableZ[i].shift = shift;
21330 unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
21331 for (j = 0; (unsigned) j < slots; j++) {
21332 nodelist[j] = NULL;
21333 }
21334 for (j = 0; (unsigned) j < oldslots; j++) {
21335 node = oldnodelist[j];
21336 while (node != NULL) {
21337 next = node->next;
21338 pos = ddHash(cuddT(node), cuddE(node), shift);
21339 node->next = nodelist[pos];
21340 nodelist[pos] = node;
21341 node = next;
21342 }
21343 }
21344 FREE(oldnodelist);
21345 
21346 #ifdef DD_VERBOSE
21347 (void) fprintf(unique->err,
21348 "rehashing layer %d: keys %d dead %d new size %d\n",
21349 i, unique->subtableZ[i].keys,
21350 unique->subtableZ[i].dead, slots);
21351 #endif
21352 
21353 /* Update global data. */
21354 unique->memused += (slots - oldslots) * sizeof(DdNode *);
21355 unique->slots += (slots - oldslots);
21356 ddFixLimits(unique);
21357 
21358 } /* end of ddRehashZdd */
21359 
21360 
21377 static int
21379 DdManager * unique,
21380 int index,
21381 int amount)
21382 {
21383 DdSubtable *newsubtables;
21384 DdNodePtr *newnodelist;
21385 DdNodePtr *newvars;
21386 DdNode *sentinel = &(unique->sentinel);
21387 int oldsize,newsize;
21388 int i,j,reorderSave;
21389 int numSlots = unique->initSlots;
21390 int *newperm, *newinvperm, *newmap;
21391 DdNode *one, *zero;
21392 
21393 oldsize = unique->size;
21394 /* Easy case: there is still room in the current table. */
21395 if (index >= 0 && index < unique->maxSize) {
21396 for (i = oldsize; i <= index; i++) {
21397 unique->subtables[i].slots = numSlots;
21398 unique->subtables[i].shift = sizeof(int) * 8 -
21399 cuddComputeFloorLog2(numSlots);
21400 unique->subtables[i].keys = 0;
21401 unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
21402 unique->subtables[i].dead = 0;
21403 unique->subtables[i].bindVar = 0;
21405 unique->subtables[i].pairIndex = 0;
21406 unique->subtables[i].varHandled = 0;
21408 
21409 unique->perm[i] = i;
21410 unique->invperm[i] = i;
21411 newnodelist = unique->subtables[i].nodelist =
21412 ALLOC(DdNodePtr, numSlots);
21413 if (newnodelist == NULL) {
21414 for (j = oldsize; j < i; j++) {
21415 FREE(unique->subtables[j].nodelist);
21416 }
21417 unique->errorCode = CUDD_MEMORY_OUT;
21418 return(0);
21419 }
21420 for (j = 0; j < numSlots; j++) {
21421 newnodelist[j] = sentinel;
21422 }
21423 }
21424 if (unique->map != NULL) {
21425 for (i = oldsize; i <= index; i++) {
21426 unique->map[i] = i;
21427 }
21428 }
21429 } else {
21430 /* The current table is too small: we need to allocate a new,
21431 ** larger one; move all old subtables, and initialize the new
21432 ** subtables up to index included.
21433 */
21434 newsize = (index < 0) ? amount : index + amount;
21435 #ifdef DD_VERBOSE
21436 (void) fprintf(unique->err,
21437 "Increasing the table size from %d to %d\n",
21438 unique->maxSize, newsize);
21439 #endif
21440 newsubtables = ALLOC(DdSubtable,newsize);
21441 if (newsubtables == NULL) {
21442 unique->errorCode = CUDD_MEMORY_OUT;
21443 return(0);
21444 }
21445 newvars = ALLOC(DdNodePtr,newsize);
21446 if (newvars == NULL) {
21447 FREE(newsubtables);
21448 unique->errorCode = CUDD_MEMORY_OUT;
21449 return(0);
21450 }
21451 newperm = ALLOC(int,newsize);
21452 if (newperm == NULL) {
21453 FREE(newsubtables);
21454 FREE(newvars);
21455 unique->errorCode = CUDD_MEMORY_OUT;
21456 return(0);
21457 }
21458 newinvperm = ALLOC(int,newsize);
21459 if (newinvperm == NULL) {
21460 FREE(newsubtables);
21461 FREE(newvars);
21462 FREE(newperm);
21463 unique->errorCode = CUDD_MEMORY_OUT;
21464 return(0);
21465 }
21466 if (unique->map != NULL) {
21467 newmap = ALLOC(int,newsize);
21468 if (newmap == NULL) {
21469 FREE(newsubtables);
21470 FREE(newvars);
21471 FREE(newperm);
21472 FREE(newinvperm);
21473 unique->errorCode = CUDD_MEMORY_OUT;
21474 return(0);
21475 }
21476 unique->memused += (newsize - unique->maxSize) * sizeof(int);
21477 }
21478 unique->memused += (newsize - unique->maxSize) * ((numSlots+1) *
21479 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
21480 if (newsize > unique->maxSizeZ) {
21481 FREE(unique->stack);
21482 unique->stack = ALLOC(DdNodePtr,newsize + 1);
21483 if (unique->stack == NULL) {
21484 FREE(newsubtables);
21485 FREE(newvars);
21486 FREE(newperm);
21487 FREE(newinvperm);
21488 if (unique->map != NULL) {
21489 FREE(newmap);
21490 }
21491 unique->errorCode = CUDD_MEMORY_OUT;
21492 return(0);
21493 }
21494 unique->stack[0] = NULL; /* to suppress harmless UMR */
21495 unique->memused +=
21496 (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
21497 * sizeof(DdNode *);
21498 }
21499 for (i = 0; i < oldsize; i++) {
21500 newsubtables[i].slots = unique->subtables[i].slots;
21501 newsubtables[i].shift = unique->subtables[i].shift;
21502 newsubtables[i].keys = unique->subtables[i].keys;
21503 newsubtables[i].maxKeys = unique->subtables[i].maxKeys;
21504 newsubtables[i].dead = unique->subtables[i].dead;
21505 newsubtables[i].nodelist = unique->subtables[i].nodelist;
21506 newsubtables[i].bindVar = unique->subtables[i].bindVar;
21507 newsubtables[i].varType = unique->subtables[i].varType;
21508 newsubtables[i].pairIndex = unique->subtables[i].pairIndex;
21509 newsubtables[i].varHandled = unique->subtables[i].varHandled;
21510 newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped;
21511 
21512 newvars[i] = unique->vars[i];
21513 newperm[i] = unique->perm[i];
21514 newinvperm[i] = unique->invperm[i];
21515 }
21516 for (i = oldsize; i <= index; i++) {
21517 newsubtables[i].slots = numSlots;
21518 newsubtables[i].shift = sizeof(int) * 8 -
21519 cuddComputeFloorLog2(numSlots);
21520 newsubtables[i].keys = 0;
21521 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
21522 newsubtables[i].dead = 0;
21523 newsubtables[i].bindVar = 0;
21524 newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
21525 newsubtables[i].pairIndex = 0;
21526 newsubtables[i].varHandled = 0;
21527 newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE;
21528 
21529 newperm[i] = i;
21530 newinvperm[i] = i;
21531 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
21532 if (newnodelist == NULL) {
21533 unique->errorCode = CUDD_MEMORY_OUT;
21534 return(0);
21535 }
21536 for (j = 0; j < numSlots; j++) {
21537 newnodelist[j] = sentinel;
21538 }
21539 }
21540 if (unique->map != NULL) {
21541 for (i = 0; i < oldsize; i++) {
21542 newmap[i] = unique->map[i];
21543 }
21544 for (i = oldsize; i <= index; i++) {
21545 newmap[i] = i;
21546 }
21547 FREE(unique->map);
21548 unique->map = newmap;
21549 }
21550 FREE(unique->subtables);
21551 unique->subtables = newsubtables;
21552 unique->maxSize = newsize;
21553 FREE(unique->vars);
21554 unique->vars = newvars;
21555 FREE(unique->perm);
21556 unique->perm = newperm;
21557 FREE(unique->invperm);
21558 unique->invperm = newinvperm;
21559 }
21560 
21561 /* Now that the table is in a coherent state, create the new
21562 ** projection functions. We need to temporarily disable reordering,
21563 ** because we cannot reorder without projection functions in place.
21564 **/
21565 if (index >= 0) {
21566 one = unique->one;
21567 zero = Cudd_Not(one);
21568 
21569 unique->size = index + 1;
21570 if (unique->tree != NULL) {
21571 unique->tree->size = ddMax(unique->tree->size, unique->size);
21572 }
21573 unique->slots += (index + 1 - oldsize) * numSlots;
21574 ddFixLimits(unique);
21575 
21576 reorderSave = unique->autoDyn;
21577 unique->autoDyn = 0;
21578 for (i = oldsize; i <= index; i++) {
21579 unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
21580 if (unique->vars[i] == NULL) {
21581 unique->autoDyn = reorderSave;
21582 for (j = oldsize; j < i; j++) {
21583 Cudd_IterDerefBdd(unique,unique->vars[j]);
21584 cuddDeallocNode(unique,unique->vars[j]);
21585 unique->vars[j] = NULL;
21586 }
21587 for (j = oldsize; j <= index; j++) {
21588 FREE(unique->subtables[j].nodelist);
21589 unique->subtables[j].nodelist = NULL;
21590 }
21591 unique->size = oldsize;
21592 unique->slots -= (index + 1 - oldsize) * numSlots;
21593 ddFixLimits(unique);
21594 return(0);
21595 }
21596 cuddRef(unique->vars[i]);
21597 }
21598 unique->autoDyn = reorderSave;
21599 }
21600 
21601 return(1);
21602 
21603 } /* end of ddResizeTable */
21604 
21605 
21606 /* end of cuddFindParent */
21607 
21608 
21622 DD_INLINE
21623 static void
21625 DdManager *unique)
21626 {
21627 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
21628 unique->cacheSlack = (int) ddMin(unique->maxCacheHard,
21630 2 * (int) unique->cacheSlots;
21631 if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0)
21632 cuddCacheResize(unique);
21633 return;
21634 
21635 } /* end of ddFixLimits */
21636 
21637 
21638 #ifndef DD_UNSORTED_FREE_LIST
21639 #ifdef DD_RED_BLACK_FREE_LIST
21640 
21652 static void
21653 cuddOrderedInsert(
21654 DdNodePtr * root,
21655 DdNodePtr node)
21656 {
21657 DdNode *scan;
21658 DdNodePtr *scanP;
21659 DdNodePtr *stack[DD_STACK_SIZE];
21660 int stackN = 0;
21661 
21662 scanP = root;
21663 while ((scan = *scanP) != NULL) {
21664 stack[stackN++] = scanP;
21665 if (DD_INSERT_COMPARE(node, scan) == 0) { /* add to page list */
21666 DD_NEXT(node) = DD_NEXT(scan);
21667 DD_NEXT(scan) = node;
21668 return;
21669 }
21670 scanP = (node < scan) ? &DD_LEFT(scan) : &DD_RIGHT(scan);
21671 }
21672 DD_RIGHT(node) = DD_LEFT(node) = DD_NEXT(node) = NULL;
21673 DD_COLOR(node) = DD_RED;
21674 *scanP = node;
21675 stack[stackN] = &node;
21676 cuddDoRebalance(stack,stackN);
21677 
21678 } /* end of cuddOrderedInsert */
21679 
21680 
21701 static DdNode *
21702 cuddOrderedThread(
21703 DdNode * root,
21704 DdNode * list)
21705 {
21706 DdNode *current, *next, *prev, *end;
21707 
21708 current = root;
21709 /* The first word in the node is used to implement a stack that holds
21710 ** the nodes from the root of the tree to the current node. Here we
21711 ** put the root of the tree at the bottom of the stack.
21712 */
21713 *((DdNodePtr *) current) = NULL;
21714 
21715 while (current != NULL) {
21716 if (DD_RIGHT(current) != NULL) {
21717 /* If possible, we follow the "right" link. Eventually we'll
21718 ** find the node with the largest address in the current tree.
21719 ** In this phase we use the first word of a node to implemen
21720 ** a stack of the nodes on the path from the root to "current".
21721 ** Also, we disconnect the "right" pointers to indicate that
21722 ** we have already followed them.
21723 */
21724 next = DD_RIGHT(current);
21725 DD_RIGHT(current) = NULL;
21726 *((DdNodePtr *)next) = current;
21727 current = next;
21728 } else {
21729 /* We can't proceed along the "right" links any further.
21730 ** Hence "current" is the largest element in the current tree.
21731 ** We make this node the new head of "list". (Repeating this
21732 ** operation until the tree is empty yields the desired linear
21733 ** threading of all nodes.)
21734 */
21735 prev = *((DdNodePtr *) current); /* save prev node on stack in prev */
21736 /* Traverse the linked list of current until the end. */
21737 for (end = current; DD_NEXT(end) != NULL; end = DD_NEXT(end));
21738 DD_NEXT(end) = list; /* attach "list" at end and make */
21739 list = current; /* "current" the new head of "list" */
21740 /* Now, if current has a "left" child, we push it on the stack.
21741 ** Otherwise, we just continue with the parent of "current".
21742 */
21743 if (DD_LEFT(current) != NULL) {
21744 next = DD_LEFT(current);
21745 *((DdNodePtr *) next) = prev;
21746 current = next;
21747 } else {
21748 current = prev;
21749 }
21750 }
21751 }
21752 
21753 return(list);
21754 
21755 } /* end of cuddOrderedThread */
21756 
21757 
21769 DD_INLINE
21770 static void
21771 cuddRotateLeft(
21772 DdNodePtr * nodeP)
21773 {
21774 DdNode *newRoot;
21775 DdNode *oldRoot = *nodeP;
21776 
21777 *nodeP = newRoot = DD_RIGHT(oldRoot);
21778 DD_RIGHT(oldRoot) = DD_LEFT(newRoot);
21779 DD_LEFT(newRoot) = oldRoot;
21780 
21781 } /* end of cuddRotateLeft */
21782 
21783 
21795 DD_INLINE
21796 static void
21797 cuddRotateRight(
21798 DdNodePtr * nodeP)
21799 {
21800 DdNode *newRoot;
21801 DdNode *oldRoot = *nodeP;
21802 
21803 *nodeP = newRoot = DD_LEFT(oldRoot);
21804 DD_LEFT(oldRoot) = DD_RIGHT(newRoot);
21805 DD_RIGHT(newRoot) = oldRoot;
21806 
21807 } /* end of cuddRotateRight */
21808 
21809 
21821 static void
21822 cuddDoRebalance(
21823 DdNodePtr ** stack,
21824 int stackN)
21825 {
21826 DdNodePtr *xP, *parentP, *grandpaP;
21827 DdNode *x, *y, *parent, *grandpa;
21828 
21829 xP = stack[stackN];
21830 x = *xP;
21831 /* Work our way back up, re-balancing the tree. */
21832 while (--stackN >= 0) {
21833 parentP = stack[stackN];
21834 parent = *parentP;
21835 if (DD_IS_BLACK(parent)) break;
21836 /* Since the root is black, here a non-null grandparent exists. */
21837 grandpaP = stack[stackN-1];
21838 grandpa = *grandpaP;
21839 if (parent == DD_LEFT(grandpa)) {
21840 y = DD_RIGHT(grandpa);
21841 if (y != NULL && DD_IS_RED(y)) {
21842 DD_COLOR(parent) = DD_BLACK;
21843 DD_COLOR(y) = DD_BLACK;
21844 DD_COLOR(grandpa) = DD_RED;
21845 x = grandpa;
21846 stackN--;
21847 } else {
21848 if (x == DD_RIGHT(parent)) {
21849 cuddRotateLeft(parentP);
21850 DD_COLOR(x) = DD_BLACK;
21851 } else {
21852 DD_COLOR(parent) = DD_BLACK;
21853 }
21854 DD_COLOR(grandpa) = DD_RED;
21855 cuddRotateRight(grandpaP);
21856 break;
21857 }
21858 } else {
21859 y = DD_LEFT(grandpa);
21860 if (y != NULL && DD_IS_RED(y)) {
21861 DD_COLOR(parent) = DD_BLACK;
21862 DD_COLOR(y) = DD_BLACK;
21863 DD_COLOR(grandpa) = DD_RED;
21864 x = grandpa;
21865 stackN--;
21866 } else {
21867 if (x == DD_LEFT(parent)) {
21868 cuddRotateRight(parentP);
21869 DD_COLOR(x) = DD_BLACK;
21870 } else {
21871 DD_COLOR(parent) = DD_BLACK;
21872 }
21873 DD_COLOR(grandpa) = DD_RED;
21874 cuddRotateLeft(grandpaP);
21875 }
21876 }
21877 }
21878 DD_COLOR(*(stack[0])) = DD_BLACK;
21879 
21880 } /* end of cuddDoRebalance */
21881 #endif
21882 #endif
21883 
21884 
21898 static void
21900 DdManager *dd,
21901 MtrNode *treenode)
21902 {
21903 MtrNode *auxnode = treenode;
21904 
21905 while (auxnode != NULL) {
21906 auxnode->low = dd->perm[auxnode->index];
21907 if (auxnode->child != NULL) {
21908 ddPatchTree(dd, auxnode->child);
21909 }
21910 auxnode = auxnode->younger;
21911 }
21912 
21913 return;
21914 
21915 } /* end of ddPatchTree */
21916 
21917 
21918 #ifdef DD_DEBUG
21919 
21930 static int
21931 cuddCheckCollisionOrdering(
21932 DdManager *unique,
21933 int i,
21934 int j)
21935 {
21936 int slots;
21937 DdNode *node, *next;
21938 DdNodePtr *nodelist;
21939 DdNode *sentinel = &(unique->sentinel);
21940 
21941 nodelist = unique->subtables[i].nodelist;
21942 slots = unique->subtables[i].slots;
21943 node = nodelist[j];
21944 if (node == sentinel) return(1);
21945 next = node->next;
21946 while (next != sentinel) {
21947 if (cuddT(node) < cuddT(next) ||
21948 (cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) {
21949 (void) fprintf(unique->err,
21950 "Unordered list: index %u, position %d\n", i, j);
21951 return(0);
21952 }
21953 node = next;
21954 next = node->next;
21955 }
21956 return(1);
21957 
21958 } /* end of cuddCheckCollisionOrdering */
21959 #endif
21960 
21961 
21962 
21963 
21975 static void
21977 DdManager *unique /* manager */,
21978 int i /* table in which the problem occurred */,
21979 const char *caller /* procedure that detected the problem */)
21980 {
21981 if (i == CUDD_CONST_INDEX) {
21982 (void) fprintf(unique->err,
21983 "%s: problem in constants\n", caller);
21984 } else if (i != -1) {
21985 (void) fprintf(unique->err,
21986 "%s: problem in table %d\n", caller, i);
21987 }
21988 (void) fprintf(unique->err, " dead count != deleted\n");
21989 (void) fprintf(unique->err, " This problem is often due to a missing \
21990 call to Cudd_Ref\n or to an extra call to Cudd_RecursiveDeref.\n \
21991 See the CUDD Programmer's Guide for additional details.");
21992 abort();
21993 
21994 } /* end of ddReportRefMess */
22108 /*---------------------------------------------------------------------------*/
22109 /* Constant declarations */
22110 /*---------------------------------------------------------------------------*/
22111 
22112 /* Random generator constants. */
22113 #define MODULUS1 2147483563
22114 #define LEQA1 40014
22115 #define LEQQ1 53668
22116 #define LEQR1 12211
22117 #define MODULUS2 2147483399
22118 #define LEQA2 40692
22119 #define LEQQ2 52774
22120 #define LEQR2 3791
22121 #define STAB_SIZE 64
22122 #define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE)
22123 
22124 /*---------------------------------------------------------------------------*/
22125 /* Stucture declarations */
22126 /*---------------------------------------------------------------------------*/
22127 
22128 /*---------------------------------------------------------------------------*/
22129 /* Type declarations */
22130 /*---------------------------------------------------------------------------*/
22131 
22132 
22133 /*---------------------------------------------------------------------------*/
22134 /* Variable declarations */
22135 /*---------------------------------------------------------------------------*/
22136 
22137 //#ifndef lint
22138 //static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.83 2012/02/05 01:07:19 fabio Exp $";
22139 //#endif
22140 
22142 
22143 static long cuddRand = 0;
22144 static long cuddRand2;
22145 static long shuffleSelect;
22147 
22148 /*---------------------------------------------------------------------------*/
22149 /* Macro declarations */
22150 /*---------------------------------------------------------------------------*/
22151 
22152 #define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ')
22153 
22154 #ifdef __cplusplus
22155 extern "C" {
22156 #endif
22157 
22160 /*---------------------------------------------------------------------------*/
22161 /* Static function prototypes */
22162 /*---------------------------------------------------------------------------*/
22163 
22164 static int dp2 (DdManager *dd, DdNode *f, st_table *t);
22165 static void ddPrintMintermAux (DdManager *dd, DdNode *node, int *list);
22166 static int ddDagInt (DdNode *n);
22167 static int cuddNodeArrayRecur (DdNode *f, DdNodePtr *table, int index);
22168 static int cuddEstimateCofactor (DdManager *dd, st_table *table, DdNode * node, int i, int phase, DdNode ** ptr);
22169 static DdNode * cuddUniqueLookup (DdManager * unique, int index, DdNode * T, DdNode * E);
22170 static int cuddEstimateCofactorSimple (DdNode * node, int i);
22171 static double ddCountMintermAux (DdNode *node, double max, DdHashTable *table);
22172 static int ddEpdCountMintermAux (DdNode *node, EpDouble *max, EpDouble *epd, st_table *table);
22173 static double ddCountPathAux (DdNode *node, st_table *table);
22174 static double ddCountPathsToNonZero (DdNode * N, st_table * table);
22175 static void ddSupportStep (DdNode *f, int *support);
22176 static void ddClearFlag (DdNode *f);
22177 static int ddLeavesInt (DdNode *n);
22178 static int ddPickArbitraryMinterms (DdManager *dd, DdNode *node, int nvars, int nminterms, char **string);
22179 
22180 static void ddFindSupport(DdManager *dd, DdNode *f, int *SP);
22181 
22184 #ifdef __cplusplus
22185 }
22186 #endif
22187 
22188 /*---------------------------------------------------------------------------*/
22189 /* Definition of exported functions */
22190 /*---------------------------------------------------------------------------*/
22191 
22192 
22208 double
22210 DdManager * manager,
22211 DdNode * node,
22212 int nvars)
22213 {
22214 double max;
22215 DdHashTable *table;
22216 double res;
22217 CUDD_VALUE_TYPE epsilon;
22218 
22219 background = manager->background;
22220 zero = Cudd_Not(manager->one);
22221 
22222 max = pow(2.0,(double)nvars);
22223 table = cuddHashTableInit(manager,1,2);
22224 if (table == NULL) {
22225 return((double)CUDD_OUT_OF_MEM);
22226 }
22227 epsilon = Cudd_ReadEpsilon(manager);
22228 Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0);
22229 res = ddCountMintermAux(node,max,table);
22230 cuddHashTableQuit(table);
22231 Cudd_SetEpsilon(manager,epsilon);
22232 
22233 return(res);
22234 
22235 } /* end of Cudd_CountMinterm */
22236 
22237 
22238 
22239 
22266 DdGen *
22268 DdManager * dd,
22269 DdNode * f,
22270 int ** cube,
22271 CUDD_VALUE_TYPE * value)
22272 {
22273 DdGen *gen;
22274 DdNode *top, *treg, *next, *nreg, *prev, *preg;
22275 int i;
22276 int nvars;
22277 
22278 /* Sanity Check. */
22279 if (dd == NULL || f == NULL) return(NULL);
22280 
22281 /* Allocate generator an initialize it. */
22282 gen = ALLOC(DdGen,1);
22283 if (gen == NULL) {
22285 return(NULL);
22286 }
22287 
22288 gen->manager = dd;
22289 gen->type = CUDD_GEN_CUBES;
22290 gen->status = CUDD_GEN_EMPTY;
22291 gen->gen.cubes.cube = NULL;
22292 gen->gen.cubes.value = DD_ZERO_VAL;
22293 gen->stack.sp = 0;
22294 gen->stack.stack = NULL;
22295 gen->node = NULL;
22296 
22297 nvars = dd->size;
22298 gen->gen.cubes.cube = ALLOC(int,nvars);
22299 if (gen->gen.cubes.cube == NULL) {
22301 FREE(gen);
22302 return(NULL);
22303 }
22304 for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2;
22305 
22306 /* The maximum stack depth is one plus the number of variables.
22307 ** because a path may have nodes at all levels, including the
22308 ** constant level.
22309 */
22310 gen->stack.stack = ALLOC(DdNodePtr, nvars+1);
22311 if (gen->stack.stack == NULL) {
22313 FREE(gen->gen.cubes.cube);
22314 FREE(gen);
22315 return(NULL);
22316 }
22317 for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL;
22318 
22319 /* Find the first cube of the onset. */
22320 gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++;
22321 
22322 while (1) {
22323 top = gen->stack.stack[gen->stack.sp-1];
22324 treg = Cudd_Regular(top);
22325 if (!cuddIsConstant(treg)) {
22326 /* Take the else branch first. */
22327 gen->gen.cubes.cube[treg->index] = 0;
22328 next = cuddE(treg);
22329 if (top != treg) next = Cudd_Not(next);
22330 gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
22331 } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
22332 /* Backtrack */
22333 while (1) {
22334 if (gen->stack.sp == 1) {
22335 /* The current node has no predecessor. */
22336 gen->status = CUDD_GEN_EMPTY;
22337 gen->stack.sp--;
22338 goto done;
22339 }
22340 prev = gen->stack.stack[gen->stack.sp-2];
22341 preg = Cudd_Regular(prev);
22342 nreg = cuddT(preg);
22343 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
22344 if (next != top) { /* follow the then branch next */
22345 gen->gen.cubes.cube[preg->index] = 1;
22346 gen->stack.stack[gen->stack.sp-1] = next;
22347 break;
22348 }
22349 /* Pop the stack and try again. */
22350 gen->gen.cubes.cube[preg->index] = 2;
22351 gen->stack.sp--;
22352 top = gen->stack.stack[gen->stack.sp-1];
22353 treg = Cudd_Regular(top);
22354 }
22355 } else {
22356 gen->status = CUDD_GEN_NONEMPTY;
22357 gen->gen.cubes.value = cuddV(top);
22358 goto done;
22359 }
22360 }
22361 
22362 done:
22363 *cube = gen->gen.cubes.cube;
22364 *value = gen->gen.cubes.value;
22365 return(gen);
22366 
22367 } /* end of Cudd_FirstCube */
22368 
22369 
22385 int
22387 DdGen * gen,
22388 int ** cube,
22389 CUDD_VALUE_TYPE * value)
22390 {
22391 DdNode *top, *treg, *next, *nreg, *prev, *preg;
22392 DdManager *dd = gen->manager;
22393 
22394 /* Backtrack from previously reached terminal node. */
22395 while (1) {
22396 if (gen->stack.sp == 1) {
22397 /* The current node has no predecessor. */
22398 gen->status = CUDD_GEN_EMPTY;
22399 gen->stack.sp--;
22400 goto done;
22401 }
22402 top = gen->stack.stack[gen->stack.sp-1];
22403 treg = Cudd_Regular(top);
22404 prev = gen->stack.stack[gen->stack.sp-2];
22405 preg = Cudd_Regular(prev);
22406 nreg = cuddT(preg);
22407 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
22408 if (next != top) { /* follow the then branch next */
22409 gen->gen.cubes.cube[preg->index] = 1;
22410 gen->stack.stack[gen->stack.sp-1] = next;
22411 break;
22412 }
22413 /* Pop the stack and try again. */
22414 gen->gen.cubes.cube[preg->index] = 2;
22415 gen->stack.sp--;
22416 }
22417 
22418 while (1) {
22419 top = gen->stack.stack[gen->stack.sp-1];
22420 treg = Cudd_Regular(top);
22421 if (!cuddIsConstant(treg)) {
22422 /* Take the else branch first. */
22423 gen->gen.cubes.cube[treg->index] = 0;
22424 next = cuddE(treg);
22425 if (top != treg) next = Cudd_Not(next);
22426 gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
22427 } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
22428 /* Backtrack */
22429 while (1) {
22430 if (gen->stack.sp == 1) {
22431 /* The current node has no predecessor. */
22432 gen->status = CUDD_GEN_EMPTY;
22433 gen->stack.sp--;
22434 goto done;
22435 }
22436 prev = gen->stack.stack[gen->stack.sp-2];
22437 preg = Cudd_Regular(prev);
22438 nreg = cuddT(preg);
22439 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
22440 if (next != top) { /* follow the then branch next */
22441 gen->gen.cubes.cube[preg->index] = 1;
22442 gen->stack.stack[gen->stack.sp-1] = next;
22443 break;
22444 }
22445 /* Pop the stack and try again. */
22446 gen->gen.cubes.cube[preg->index] = 2;
22447 gen->stack.sp--;
22448 top = gen->stack.stack[gen->stack.sp-1];
22449 treg = Cudd_Regular(top);
22450 }
22451 } else {
22452 gen->status = CUDD_GEN_NONEMPTY;
22453 gen->gen.cubes.value = cuddV(top);
22454 goto done;
22455 }
22456 }
22457 
22458 done:
22459 if (gen->status == CUDD_GEN_EMPTY) return(0);
22460 *cube = gen->gen.cubes.cube;
22461 *value = gen->gen.cubes.value;
22462 return(1);
22463 
22464 } /* end of Cudd_NextCube */
22465 
22466 
22496 DdGen *
22498 DdManager *dd,
22499 DdNode *l,
22500 DdNode *u,
22501 int **cube)
22502 {
22503 DdGen *gen;
22504 DdNode *implicant, *prime, *tmp;
22505 int length, result;
22506 
22507 /* Sanity Check. */
22508 if (dd == NULL || l == NULL || u == NULL) return(NULL);
22509 
22510 /* Allocate generator an initialize it. */
22511 gen = ALLOC(DdGen,1);
22512 if (gen == NULL) {
22514 return(NULL);
22515 }
22516 
22517 gen->manager = dd;
22518 gen->type = CUDD_GEN_PRIMES;
22519 gen->status = CUDD_GEN_EMPTY;
22520 gen->gen.primes.cube = NULL;
22521 gen->gen.primes.ub = u;
22522 gen->stack.sp = 0;
22523 gen->stack.stack = NULL;
22524 gen->node = l;
22525 cuddRef(l);
22526 
22527 gen->gen.primes.cube = ALLOC(int,dd->size);
22528 if (gen->gen.primes.cube == NULL) {
22530 FREE(gen);
22531 return(NULL);
22532 }
22533 
22534 if (gen->node == Cudd_ReadLogicZero(dd)) {
22535 gen->status = CUDD_GEN_EMPTY;
22536 } else {
22537 implicant = Cudd_LargestCube(dd,gen->node,&length);
22538 if (implicant == NULL) {
22539 Cudd_RecursiveDeref(dd,gen->node);
22540 FREE(gen->gen.primes.cube);
22541 FREE(gen);
22542 return(NULL);
22543 }
22544 cuddRef(implicant);
22545 prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
22546 if (prime == NULL) {
22547 Cudd_RecursiveDeref(dd,gen->node);
22548 Cudd_RecursiveDeref(dd,implicant);
22549 FREE(gen->gen.primes.cube);
22550 FREE(gen);
22551 return(NULL);
22552 }
22553 cuddRef(prime);
22554 Cudd_RecursiveDeref(dd,implicant);
22555 tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
22556 if (tmp == NULL) {
22557 Cudd_RecursiveDeref(dd,gen->node);
22558 Cudd_RecursiveDeref(dd,prime);
22559 FREE(gen->gen.primes.cube);
22560 FREE(gen);
22561 return(NULL);
22562 }
22563 cuddRef(tmp);
22564 Cudd_RecursiveDeref(dd,gen->node);
22565 gen->node = tmp;
22566 result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
22567 if (result == 0) {
22568 Cudd_RecursiveDeref(dd,gen->node);
22569 Cudd_RecursiveDeref(dd,prime);
22570 FREE(gen->gen.primes.cube);
22571 FREE(gen);
22572 return(NULL);
22573 }
22574 Cudd_RecursiveDeref(dd,prime);
22575 gen->status = CUDD_GEN_NONEMPTY;
22576 }
22577 *cube = gen->gen.primes.cube;
22578 return(gen);
22579 
22580 } /* end of Cudd_FirstPrime */
22581 
22582 
22598 int
22600 DdGen *gen,
22601 int **cube)
22602 {
22603 DdNode *implicant, *prime, *tmp;
22604 DdManager *dd = gen->manager;
22605 int length, result;
22606 
22607 if (gen->node == Cudd_ReadLogicZero(dd)) {
22608 gen->status = CUDD_GEN_EMPTY;
22609 } else {
22610 implicant = Cudd_LargestCube(dd,gen->node,&length);
22611 if (implicant == NULL) {
22612 gen->status = CUDD_GEN_EMPTY;
22613 return(0);
22614 }
22615 cuddRef(implicant);
22616 prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
22617 if (prime == NULL) {
22618 Cudd_RecursiveDeref(dd,implicant);
22619 gen->status = CUDD_GEN_EMPTY;
22620 return(0);
22621 }
22622 cuddRef(prime);
22623 Cudd_RecursiveDeref(dd,implicant);
22624 tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
22625 if (tmp == NULL) {
22626 Cudd_RecursiveDeref(dd,prime);
22627 gen->status = CUDD_GEN_EMPTY;
22628 return(0);
22629 }
22630 cuddRef(tmp);
22631 Cudd_RecursiveDeref(dd,gen->node);
22632 gen->node = tmp;
22633 result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
22634 if (result == 0) {
22635 Cudd_RecursiveDeref(dd,prime);
22636 gen->status = CUDD_GEN_EMPTY;
22637 return(0);
22638 }
22639 Cudd_RecursiveDeref(dd,prime);
22640 gen->status = CUDD_GEN_NONEMPTY;
22641 }
22642 if (gen->status == CUDD_GEN_EMPTY) return(0);
22643 *cube = gen->gen.primes.cube;
22644 return(1);
22645 
22646 } /* end of Cudd_NextPrime */
22647 
22648 
22649 
22668 int
22670 DdManager *dd,
22671 DdNode *cube,
22672 int *array)
22673 {
22674 DdNode *scan, *t, *e;
22675 int i;
22676 int size = Cudd_ReadSize(dd);
22677 DdNode *zero = Cudd_Not(DD_ONE(dd));
22678 
22679 for (i = size-1; i >= 0; i--) {
22680 array[i] = 2;
22681 }
22682 scan = cube;
22683 while (!Cudd_IsConstant(scan)) {
22684 int index = Cudd_Regular(scan)->index;
22685 cuddGetBranches(scan,&t,&e);
22686 if (t == zero) {
22687 array[index] = 0;
22688 scan = e;
22689 } else if (e == zero) {
22690 array[index] = 1;
22691 scan = t;
22692 } else {
22693 return(0); /* cube is not a cube */
22694 }
22695 }
22696 if (scan == zero) {
22697 return(0);
22698 } else {
22699 return(1);
22700 }
22701 
22702 } /* end of Cudd_BddToCubeArray */
22703 
22704 
22722 DdGen *
22724 DdManager * dd,
22725 DdNode * f,
22726 DdNode ** node)
22727 {
22728 DdGen *gen;
22729 int size;
22730 
22731 /* Sanity Check. */
22732 if (dd == NULL || f == NULL) return(NULL);
22733 
22734 /* Allocate generator an initialize it. */
22735 gen = ALLOC(DdGen,1);
22736 if (gen == NULL) {
22738 return(NULL);
22739 }
22740 
22741 gen->manager = dd;
22742 gen->type = CUDD_GEN_NODES;
22743 gen->status = CUDD_GEN_EMPTY;
22744 gen->stack.sp = 0;
22745 gen->node = NULL;
22746 
22747 /* Collect all the nodes on the generator stack for later perusal. */
22748 gen->stack.stack = cuddNodeArray(Cudd_Regular(f), &size);
22749 if (gen->stack.stack == NULL) {
22750 FREE(gen);
22752 return(NULL);
22753 }
22754 gen->gen.nodes.size = size;
22755 
22756 /* Find the first node. */
22757 if (gen->stack.sp < gen->gen.nodes.size) {
22758 gen->status = CUDD_GEN_NONEMPTY;
22759 gen->node = gen->stack.stack[gen->stack.sp];
22760 *node = gen->node;
22761 }
22762 
22763 return(gen);
22764 
22765 } /* end of Cudd_FirstNode */
22766 
22767 
22781 int
22783 DdGen * gen,
22784 DdNode ** node)
22785 {
22786 /* Find the next node. */
22787 gen->stack.sp++;
22788 if (gen->stack.sp < gen->gen.nodes.size) {
22789 gen->node = gen->stack.stack[gen->stack.sp];
22790 *node = gen->node;
22791 return(1);
22792 } else {
22793 gen->status = CUDD_GEN_EMPTY;
22794 return(0);
22795 }
22796 
22797 } /* end of Cudd_NextNode */
22798 
22799 
22813 int
22815 DdGen * gen)
22816 {
22817 if (gen == NULL) return(0);
22818 switch (gen->type) {
22819 case CUDD_GEN_CUBES:
22820 case CUDD_GEN_ZDD_PATHS:
22821 FREE(gen->gen.cubes.cube);
22822 FREE(gen->stack.stack);
22823 break;
22824 case CUDD_GEN_PRIMES:
22825 FREE(gen->gen.primes.cube);
22826 Cudd_RecursiveDeref(gen->manager,gen->node);
22827 break;
22828 case CUDD_GEN_NODES:
22829 FREE(gen->stack.stack);
22830 break;
22831 default:
22832 return(0);
22833 }
22834 FREE(gen);
22835 return(0);
22836 
22837 } /* end of Cudd_GenFree */
22838 
22839 
22853 int
22855 DdGen * gen)
22856 {
22857 if (gen == NULL) return(1);
22858 return(gen->status == CUDD_GEN_EMPTY);
22859 
22860 } /* end of Cudd_IsGenEmpty */
22861 
22862 
22880 long
22882 {
22883 int i; /* index in the shuffle table */
22884 long int w; /* work variable */
22885 
22886 /* cuddRand == 0 if the geneartor has not been initialized yet. */
22887 if (cuddRand == 0) Cudd_Srandom(1);
22888 
22889 /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding
22890 ** overflows by Schrage's method.
22891 */
22892 w = cuddRand / LEQQ1;
22893 cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
22894 cuddRand += (cuddRand < 0) * MODULUS1;
22895 
22896 /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding
22897 ** overflows by Schrage's method.
22898 */
22899 w = cuddRand2 / LEQQ2;
22900 cuddRand2 = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2;
22901 cuddRand2 += (cuddRand2 < 0) * MODULUS2;
22902 
22903 /* cuddRand is shuffled with the Bays-Durham algorithm.
22904 ** shuffleSelect and cuddRand2 are combined to generate the output.
22905 */
22906 
22907 /* Pick one element from the shuffle table; "i" will be in the range
22908 ** from 0 to STAB_SIZE-1.
22909 */
22910 i = (int) (shuffleSelect / STAB_DIV);
22911 /* Mix the element of the shuffle table with the current iterate of
22912 ** the second sub-generator, and replace the chosen element of the
22913 ** shuffle table with the current iterate of the first sub-generator.
22914 */
22916 shuffleTable[i] = cuddRand;
22917 shuffleSelect += (shuffleSelect < 1) * (MODULUS1 - 1);
22918 /* Since shuffleSelect != 0, and we want to be able to return 0,
22919 ** here we subtract 1 before returning.
22920 */
22921 return(shuffleSelect - 1);
22922 
22923 } /* end of Cudd_Random */
22924 
22925 
22942 void
22944 long seed)
22945 {
22946 int i;
22947 
22948 if (seed < 0) cuddRand = -seed;
22949 else if (seed == 0) cuddRand = 1;
22950 else cuddRand = seed;
22952 /* Load the shuffle table (after 11 warm-ups). */
22953 for (i = 0; i < STAB_SIZE + 11; i++) {
22954 long int w;
22955 w = cuddRand / LEQQ1;
22956 cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
22957 cuddRand += (cuddRand < 0) * MODULUS1;
22959 }
22961 
22962 } /* end of Cudd_Srandom */
22963 
22964 
22965 
22981 void
22983 long size /* size of the allocation that failed */)
22984 {
22985 (void) fflush(stdout);
22986 (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size);
22987 return;
22988 
22989 } /* end of Cudd_OutOfMem */
22990 
22991 
22992 /*---------------------------------------------------------------------------*/
22993 /* Definition of internal functions */
22994 /*---------------------------------------------------------------------------*/
22995 
22996 
23012 int
23014 DdNode * f,
23015 st_table * visited)
23016 {
23017 DdNode *T, *E;
23018 int retval;
23019 
23020 #ifdef DD_DEBUG
23022 #endif
23023 
23024 /* If already visited, nothing to do. */
23025 if (st_is_member(visited, (char *) f) == 1)
23026 return(1);
23027 
23028 /* Check for abnormal condition that should never happen. */
23029 if (f == NULL)
23030 return(0);
23031 
23032 /* Mark node as visited. */
23033 if (st_add_direct(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
23034 return(0);
23035 
23036 /* Check terminal case. */
23037 if (cuddIsConstant(f))
23038 return(1);
23039 
23040 /* Recursive calls. */
23041 T = cuddT(f);
23042 retval = cuddCollectNodes(T,visited);
23043 if (retval != 1) return(retval);
23044 E = Cudd_Regular(cuddE(f));
23045 retval = cuddCollectNodes(E,visited);
23046 return(retval);
23047 
23048 } /* end of cuddCollectNodes */
23049 
23050 
23066 DdNodePtr *
23068 DdNode *f,
23069 int *n)
23070 {
23071 DdNodePtr *table;
23072 int size, retval;
23073 
23074 size = ddDagInt(Cudd_Regular(f));
23075 table = ALLOC(DdNodePtr, size);
23076 if (table == NULL) {
23078 return(NULL);
23079 }
23080 
23081 retval = cuddNodeArrayRecur(f, table, 0);
23082 assert(retval == size);
23083 
23084 *n = size;
23085 return(table);
23086 
23087 } /* cuddNodeArray */
23088 
23089 
23090 /*---------------------------------------------------------------------------*/
23091 /* Definition of static functions */
23092 /*---------------------------------------------------------------------------*/
23093 
23094 
23105 static int
23107 DdManager *dd,
23108 DdNode * f,
23109 st_table * t)
23110 {
23111 DdNode *g, *n, *N;
23112 int T,E;
23113 
23114 if (f == NULL) {
23115 return(0);
23116 }
23117 g = Cudd_Regular(f);
23118 if (cuddIsConstant(g)) {
23119 #if SIZEOF_VOID_P == 8
23120 (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f),
23121 (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g));
23122 #else
23123 (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f),
23124 (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g));
23125 #endif
23126 return(1);
23127 }
23128 if (st_is_member(t,(char *) g) == 1) {
23129 return(1);
23130 }
23131 if (st_add_direct(t,(char *) g,NULL) == ST_OUT_OF_MEM)
23132 return(0);
23133 #ifdef DD_STATS
23134 #if SIZEOF_VOID_P == 8
23135 (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f),
23136 (ptruint) g / (ptruint) sizeof(DdNode), g->index, g->ref);
23137 #else
23138 (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f),
23139 (ptruint) g / (ptruint) sizeof(DdNode),g->index,g->ref);
23140 #endif
23141 #else
23142 #if SIZEOF_VOID_P == 8
23143 (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %u\t", bang(f),
23144 (ptruint) g / (ptruint) sizeof(DdNode),g->index);
23145 #else
23146 (void) fprintf(dd->out,"ID = %c0x%x\tindex = %hu\t", bang(f),
23147 (ptruint) g / (ptruint) sizeof(DdNode),g->index);
23148 #endif
23149 #endif
23150 n = cuddT(g);
23151 if (cuddIsConstant(n)) {
23152 (void) fprintf(dd->out,"T = %-9g\t",cuddV(n));
23153 T = 1;
23154 } else {
23155 #if SIZEOF_VOID_P == 8
23156 (void) fprintf(dd->out,"T = 0x%lx\t",(ptruint) n / (ptruint) sizeof(DdNode));
23157 #else
23158 (void) fprintf(dd->out,"T = 0x%x\t",(ptruint) n / (ptruint) sizeof(DdNode));
23159 #endif
23160 T = 0;
23161 }
23162 
23163 n = cuddE(g);
23164 N = Cudd_Regular(n);
23165 if (cuddIsConstant(N)) {
23166 (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N));
23167 E = 1;
23168 } else {
23169 #if SIZEOF_VOID_P == 8
23170 (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode));
23171 #else
23172 (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode));
23173 #endif
23174 E = 0;
23175 }
23176 if (E == 0) {
23177 if (dp2(dd,N,t) == 0)
23178 return(0);
23179 }
23180 if (T == 0) {
23181 if (dp2(dd,cuddT(g),t) == 0)
23182 return(0);
23183 }
23184 return(1);
23185 
23186 } /* end of dp2 */
23187 
23188 
23198 static void
23200 DdManager * dd /* manager */,
23201 DdNode * node /* current node */,
23202 int * list /* current recursion path */)
23203 {
23204 DdNode *N,*Nv,*Nnv;
23205 int i,v,index;
23206 
23207 N = Cudd_Regular(node);
23208 
23209 if (cuddIsConstant(N)) {
23210 /* Terminal case: Print one cube based on the current recursion
23211 ** path, unless we have reached the background value (ADDs) or
23212 ** the logical zero (BDDs).
23213 */
23214 if (node != background && node != zero) {
23215 for (i = 0; i < dd->size; i++) {
23216 v = list[i];
23217 if (v == 0) (void) fprintf(dd->out,"0");
23218 else if (v == 1) (void) fprintf(dd->out,"1");
23219 else (void) fprintf(dd->out,"-");
23220 }
23221 (void) fprintf(dd->out," % g\n", cuddV(node));
23222 }
23223 } else {
23224 Nv = cuddT(N);
23225 Nnv = cuddE(N);
23226 if (Cudd_IsComplement(node)) {
23227 Nv = Cudd_Not(Nv);
23228 Nnv = Cudd_Not(Nnv);
23229 }
23230 index = N->index;
23231 list[index] = 0;
23232 ddPrintMintermAux(dd,Nnv,list);
23233 list[index] = 1;
23234 ddPrintMintermAux(dd,Nv,list);
23235 list[index] = 2;
23236 }
23237 return;
23238 
23239 } /* end of ddPrintMintermAux */
23240 
23241 
23252 static int
23254 DdNode * n)
23255 {
23256 int tval, eval;
23257 
23258 if (Cudd_IsComplement(n->next)) {
23259 return(0);
23260 }
23261 n->next = Cudd_Not(n->next);
23262 if (cuddIsConstant(n)) {
23263 return(1);
23264 }
23265 tval = ddDagInt(cuddT(n));
23266 eval = ddDagInt(Cudd_Regular(cuddE(n)));
23267 return(1 + tval + eval);
23268 
23269 } /* end of ddDagInt */
23270 
23271 
23287 static int
23289 DdNode *f,
23290 DdNodePtr *table,
23291 int index)
23292 {
23293 int tindex, eindex;
23294 
23295 if (!Cudd_IsComplement(f->next)) {
23296 return(index);
23297 }
23298 /* Clear visited flag. */
23299 f->next = Cudd_Regular(f->next);
23300 if (cuddIsConstant(f)) {
23301 table[index] = f;
23302 return(index + 1);
23303 }
23304 tindex = cuddNodeArrayRecur(cuddT(f), table, index);
23305 eindex = cuddNodeArrayRecur(Cudd_Regular(cuddE(f)), table, tindex);
23306 table[eindex] = f;
23307 return(eindex + 1);
23308 
23309 } /* end of cuddNodeArrayRecur */
23310 
23311 
23327 static int
23329 DdManager *dd,
23330 st_table *table,
23331 DdNode * node,
23332 int i,
23333 int phase,
23334 DdNode ** ptr)
23335 {
23336 int tval, eval, val;
23337 DdNode *ptrT, *ptrE;
23338 
23339 if (Cudd_IsComplement(node->next)) {
23340 if (!st_lookup(table,(char *)node,(char **)ptr)) {
23341 if (st_add_direct(table,(char *)node,(char *)node) ==
23343 return(CUDD_OUT_OF_MEM);
23344 *ptr = node;
23345 }
23346 return(0);
23347 }
23348 node->next = Cudd_Not(node->next);
23349 if (cuddIsConstant(node)) {
23350 *ptr = node;
23351 if (st_add_direct(table,(char *)node,(char *)node) == ST_OUT_OF_MEM)
23352 return(CUDD_OUT_OF_MEM);
23353 return(1);
23354 }
23355 if ((int) node->index == i) {
23356 if (phase == 1) {
23357 *ptr = cuddT(node);
23358 val = ddDagInt(cuddT(node));
23359 } else {
23360 *ptr = cuddE(node);
23361 val = ddDagInt(Cudd_Regular(cuddE(node)));
23362 }
23363 if (node->ref > 1) {
23364 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
23366 return(CUDD_OUT_OF_MEM);
23367 }
23368 return(val);
23369 }
23370 if (dd->perm[node->index] > dd->perm[i]) {
23371 *ptr = node;
23372 tval = ddDagInt(cuddT(node));
23373 eval = ddDagInt(Cudd_Regular(cuddE(node)));
23374 if (node->ref > 1) {
23375 if (st_add_direct(table,(char *)node,(char *)node) ==
23377 return(CUDD_OUT_OF_MEM);
23378 }
23379 val = 1 + tval + eval;
23380 return(val);
23381 }
23382 tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT);
23383 eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i,
23384 phase,&ptrE);
23385 ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node)));
23386 if (ptrT == ptrE) { /* recombination */
23387 *ptr = ptrT;
23388 val = tval;
23389 if (node->ref > 1) {
23390 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
23392 return(CUDD_OUT_OF_MEM);
23393 }
23394 } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) &&
23395 (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) {
23396 if (Cudd_IsComplement((*ptr)->next)) {
23397 val = 0;
23398 } else {
23399 val = 1 + tval + eval;
23400 }
23401 if (node->ref > 1) {
23402 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
23404 return(CUDD_OUT_OF_MEM);
23405 }
23406 } else {
23407 *ptr = node;
23408 val = 1 + tval + eval;
23409 }
23410 return(val);
23411 
23412 } /* end of cuddEstimateCofactor */
23413 
23414 
23427 static DdNode *
23429 DdManager * unique,
23430 int index,
23431 DdNode * T,
23432 DdNode * E)
23433 {
23434 int posn;
23435 unsigned int level;
23436 DdNodePtr *nodelist;
23437 DdNode *looking;
23438 DdSubtable *subtable;
23439 
23440 if (index >= unique->size) {
23441 return(NULL);
23442 }
23443 
23444 level = unique->perm[index];
23445 subtable = &(unique->subtables[level]);
23446 
23447 #ifdef DD_DEBUG
23448 assert(level < (unsigned) cuddI(unique,T->index));
23449 assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
23450 #endif
23451 
23452 posn = ddHash(T, E, subtable->shift);
23453 nodelist = subtable->nodelist;
23454 looking = nodelist[posn];
23455 
23456 while (T < cuddT(looking)) {
23457 looking = Cudd_Regular(looking->next);
23458 }
23459 while (T == cuddT(looking) && E < cuddE(looking)) {
23460 looking = Cudd_Regular(looking->next);
23461 }
23462 if (cuddT(looking) == T && cuddE(looking) == E) {
23463 return(looking);
23464 }
23465 
23466 return(NULL);
23467 
23468 } /* end of cuddUniqueLookup */
23469 
23470 
23486 static int
23488 DdNode * node,
23489 int i)
23490 {
23491 int tval, eval;
23492 
23493 if (Cudd_IsComplement(node->next)) {
23494 return(0);
23495 }
23496 node->next = Cudd_Not(node->next);
23497 if (cuddIsConstant(node)) {
23498 return(1);
23499 }
23500 tval = cuddEstimateCofactorSimple(cuddT(node),i);
23501 if ((int) node->index == i) return(tval);
23503 return(1 + tval + eval);
23504 
23505 } /* end of cuddEstimateCofactorSimple */
23506 
23507 
23526 static double
23528 DdNode * node,
23529 double max,
23530 DdHashTable * table)
23531 {
23532 DdNode *N, *Nt, *Ne;
23533 double min, minT, minE;
23534 DdNode *res;
23535 
23536 N = Cudd_Regular(node);
23537 
23538 if (cuddIsConstant(N)) {
23539 if (node == background || node == zero) {
23540 return(0.0);
23541 } else {
23542 return(max);
23543 }
23544 }
23545 if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
23546 min = cuddV(res);
23547 if (res->ref == 0) {
23548 table->manager->dead++;
23549 table->manager->constants.dead++;
23550 }
23551 return(min);
23552 }
23553 
23554 Nt = cuddT(N); Ne = cuddE(N);
23555 if (Cudd_IsComplement(node)) {
23556 Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
23557 }
23558 
23559 minT = ddCountMintermAux(Nt,max,table);
23560 if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
23561 minT *= 0.5;
23562 minE = ddCountMintermAux(Ne,max,table);
23563 if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
23564 minE *= 0.5;
23565 min = minT + minE;
23566 
23567 if (N->ref != 1) {
23568 ptrint fanout = (ptrint) N->ref;
23569 cuddSatDec(fanout);
23570 res = cuddUniqueConst(table->manager,min);
23571 if (!cuddHashTableInsert1(table,node,res,fanout)) {
23572 cuddRef(res); Cudd_RecursiveDeref(table->manager, res);
23573 return((double)CUDD_OUT_OF_MEM);
23574 }
23575 }
23576 
23577 return(min);
23578 
23579 } /* end of ddCountMintermAux */
23580 
23581 
23599 static double
23601 DdNode * node,
23602 st_table * table)
23603 {
23604 
23605 DdNode *Nv, *Nnv;
23606 double paths, *ppaths, paths1, paths2;
23607 double *dummy;
23608 
23609 
23610 if (cuddIsConstant(node)) {
23611 return(1.0);
23612 }
23613 if (st_lookup(table, node, &dummy)) {
23614 paths = *dummy;
23615 return(paths);
23616 }
23617 
23618 Nv = cuddT(node); Nnv = cuddE(node);
23619 
23620 paths1 = ddCountPathAux(Nv,table);
23621 if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
23622 paths2 = ddCountPathAux(Cudd_Regular(Nnv),table);
23623 if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
23624 paths = paths1 + paths2;
23625 
23626 ppaths = ALLOC(double,1);
23627 if (ppaths == NULL) {
23628 return((double)CUDD_OUT_OF_MEM);
23629 }
23630 
23631 *ppaths = paths;
23632 
23633 if (st_add_direct(table,(char *)node, (char *)ppaths) == ST_OUT_OF_MEM) {
23634 FREE(ppaths);
23635 return((double)CUDD_OUT_OF_MEM);
23636 }
23637 return(paths);
23638 
23639 } /* end of ddCountPathAux */
23640 
23641 
23660 static int
23662 DdNode * node,
23663 EpDouble * max,
23664 EpDouble * epd,
23665 st_table * table)
23666 {
23667 DdNode *Nt, *Ne;
23668 EpDouble *min, minT, minE;
23669 EpDouble *res;
23670 int status;
23671 
23672 /* node is assumed to be regular */
23673 if (cuddIsConstant(node)) {
23674 if (node == background || node == zero) {
23675 EpdMakeZero(epd, 0);
23676 } else {
23677 EpdCopy(max, epd);
23678 }
23679 return(0);
23680 }
23681 if (node->ref != 1 && st_lookup(table, node, &res)) {
23682 EpdCopy(res, epd);
23683 return(0);
23684 }
23685 
23686 Nt = cuddT(node); Ne = cuddE(node);
23687 
23688 status = ddEpdCountMintermAux(Nt,max,&minT,table);
23689 if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
23690 EpdMultiply(&minT, (double)0.5);
23691 status = ddEpdCountMintermAux(Cudd_Regular(Ne),max,&minE,table);
23692 if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
23693 if (Cudd_IsComplement(Ne)) {
23694 EpdSubtract3(max, &minE, epd);
23695 EpdCopy(epd, &minE);
23696 }
23697 EpdMultiply(&minE, (double)0.5);
23698 EpdAdd3(&minT, &minE, epd);
23699 
23700 if (node->ref > 1) {
23701 min = EpdAlloc();
23702 if (!min)
23703 return(CUDD_OUT_OF_MEM);
23704 EpdCopy(epd, min);
23705 if (st_insert(table, (char *)node, (char *)min) == ST_OUT_OF_MEM) {
23706 EpdFree(min);
23707 return(CUDD_OUT_OF_MEM);
23708 }
23709 }
23710 
23711 return(0);
23712 
23713 } /* end of ddEpdCountMintermAux */
23714 
23715 
23732 static double
23734 DdNode * N,
23735 st_table * table)
23736 {
23737 
23738 DdNode *node, *Nt, *Ne;
23739 double paths, *ppaths, paths1, paths2;
23740 double *dummy;
23741 
23742 node = Cudd_Regular(N);
23743 if (cuddIsConstant(node)) {
23744 return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL));
23745 }
23746 if (st_lookup(table, N, &dummy)) {
23747 paths = *dummy;
23748 return(paths);
23749 }
23750 
23751 Nt = cuddT(node); Ne = cuddE(node);
23752 if (node != N) {
23753 Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
23754 }
23755 
23756 paths1 = ddCountPathsToNonZero(Nt,table);
23757 if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
23758 paths2 = ddCountPathsToNonZero(Ne,table);
23759 if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
23760 paths = paths1 + paths2;
23761 
23762 ppaths = ALLOC(double,1);
23763 if (ppaths == NULL) {
23764 return((double)CUDD_OUT_OF_MEM);
23765 }
23766 
23767 *ppaths = paths;
23768 
23769 if (st_add_direct(table,(char *)N, (char *)ppaths) == ST_OUT_OF_MEM) {
23770 FREE(ppaths);
23771 return((double)CUDD_OUT_OF_MEM);
23772 }
23773 return(paths);
23774 
23775 } /* end of ddCountPathsToNonZero */
23776 
23777 
23791 static void
23793 DdNode * f,
23794 int * support)
23795 {
23796 if (cuddIsConstant(f) || Cudd_IsComplement(f->next))
23797 return;
23798 
23799 support[f->index] = 1;
23800 ddSupportStep(cuddT(f),support);
23801 ddSupportStep(Cudd_Regular(cuddE(f)),support);
23802 /* Mark as visited. */
23803 f->next = Cudd_Complement(f->next);
23804 
23805 } /* end of ddSupportStep */
23806 
23807 
23820 static void
23822 DdNode * f)
23823 {
23824 if (!Cudd_IsComplement(f->next)) {
23825 return;
23826 }
23827 /* Clear visited flag. */
23828 f->next = Cudd_Regular(f->next);
23829 if (cuddIsConstant(f)) {
23830 return;
23831 }
23832 ddClearFlag(cuddT(f));
23834 return;
23835 
23836 } /* end of ddClearFlag */
23837 
23838 
23851 static int
23853 DdNode * n)
23854 {
23855 int tval, eval;
23856 
23857 if (Cudd_IsComplement(n->next)) {
23858 return(0);
23859 }
23860 n->next = Cudd_Not(n->next);
23861 if (cuddIsConstant(n)) {
23862 return(1);
23863 }
23864 tval = ddLeavesInt(cuddT(n));
23865 eval = ddLeavesInt(Cudd_Regular(cuddE(n)));
23866 return(tval + eval);
23867 
23868 } /* end of ddLeavesInt */
23869 
23870 
23883 static int
23885 DdManager *dd,
23886 DdNode *node,
23887 int nvars,
23888 int nminterms,
23889 char **string)
23890 {
23891 DdNode *N, *T, *E;
23892 DdNode *one, *bzero;
23893 int i, t, result;
23894 double min1, min2;
23895 
23896 if (string == NULL || node == NULL) return(0);
23897 
23898 /* The constant 0 function has no on-set cubes. */
23899 one = DD_ONE(dd);
23900 bzero = Cudd_Not(one);
23901 if (nminterms == 0 || node == bzero) return(1);
23902 if (node == one) {
23903 return(1);
23904 }
23905 
23906 N = Cudd_Regular(node);
23907 T = cuddT(N); E = cuddE(N);
23908 if (Cudd_IsComplement(node)) {
23909 T = Cudd_Not(T); E = Cudd_Not(E);
23910 }
23911 
23912 min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0;
23913 if (min1 == (double)CUDD_OUT_OF_MEM) return(0);
23914 min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0;
23915 if (min2 == (double)CUDD_OUT_OF_MEM) return(0);
23916 
23917 t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5);
23918 for (i = 0; i < t; i++)
23919 string[i][N->index] = '1';
23920 for (i = t; i < nminterms; i++)
23921 string[i][N->index] = '0';
23922 
23923 result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]);
23924 if (result == 0)
23925 return(0);
23926 result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]);
23927 return(result);
23928 
23929 } /* end of ddPickArbitraryMinterms */
23930 
23931 
23932 /* end of ddPickRepresentativeCube */
23933 
23934 
23935 /* end of ddEpdFree */
23936 
23937 
23952 static void
23954 DdManager *dd,
23955 DdNode *f,
23956 int *SP)
23957 {
23958 int index;
23959 DdNode *var;
23960 
23961 if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) {
23962 return;
23963 }
23964 
23965 index = f->index;
23966 var = dd->vars[index];
23967 /* It is possible that var is embedded in f. That causes no problem,
23968 ** though, because if we see it after encountering another node with
23969 ** the same index, nothing is supposed to happen.
23970 */
23971 if (!Cudd_IsComplement(var->next)) {
23972 var->next = Cudd_Complement(var->next);
23973 dd->stack[*SP] = (DdNode *)(ptrint) index;
23974 (*SP)++;
23975 }
23976 ddFindSupport(dd, cuddT(f), SP);
23977 ddFindSupport(dd, Cudd_Regular(cuddE(f)), SP);
23978 /* Mark as visited. */
23979 f->next = Cudd_Complement(f->next);
23980 
23981 } /* end of ddFindSupport */
23982 
23983 
23984 /* end of ddClearVars */
23985 
23986 
23987 /* end of indexCompare */
24049 /*---------------------------------------------------------------------------*/
24050 /* Constant declarations */
24051 /*---------------------------------------------------------------------------*/
24052 
24053 
24054 /*---------------------------------------------------------------------------*/
24055 /* Stucture declarations */
24056 /*---------------------------------------------------------------------------*/
24057 
24058 
24059 /*---------------------------------------------------------------------------*/
24060 /* Type declarations */
24061 /*---------------------------------------------------------------------------*/
24062 
24063 
24064 /*---------------------------------------------------------------------------*/
24065 /* Variable declarations */
24066 /*---------------------------------------------------------------------------*/
24067 
24068 //#ifndef lint
24069 //static char rcsid[] DD_UNUSED = "$Id: cuddWindow.c,v 1.15 2012/02/05 01:07:19 fabio Exp $";
24070 //#endif
24071 
24072 #ifdef DD_STATS
24073 extern int ddTotalNumberSwapping;
24074 extern int ddTotalNISwaps;
24075 #endif
24076 
24077 /*---------------------------------------------------------------------------*/
24078 /* Macro declarations */
24079 /*---------------------------------------------------------------------------*/
24080 
24081 
24084 /*---------------------------------------------------------------------------*/
24085 /* Static function prototypes */
24086 /*---------------------------------------------------------------------------*/
24087 
24088 static int ddWindow2 (DdManager *table, int low, int high);
24089 static int ddWindowConv2 (DdManager *table, int low, int high);
24090 static int ddPermuteWindow3 (DdManager *table, int x);
24091 static int ddWindow3 (DdManager *table, int low, int high);
24092 static int ddWindowConv3 (DdManager *table, int low, int high);
24093 static int ddPermuteWindow4 (DdManager *table, int w);
24094 static int ddWindow4 (DdManager *table, int low, int high);
24095 static int ddWindowConv4 (DdManager *table, int low, int high);
24096 
24100 /*---------------------------------------------------------------------------*/
24101 /* Definition of exported functions */
24102 /*---------------------------------------------------------------------------*/
24103 
24104 /*---------------------------------------------------------------------------*/
24105 /* Definition of internal functions */
24106 /*---------------------------------------------------------------------------*/
24107 
24108 
24122 int
24124 DdManager * table /* DD table */,
24125 int low /* lowest index to reorder */,
24126 int high /* highest index to reorder */,
24127 Cudd_ReorderingType submethod /* window reordering option */)
24128 {
24129 
24130 int res;
24131 #ifdef DD_DEBUG
24132 int supposedOpt;
24133 #endif
24134 
24135 switch (submethod) {
24137 res = ddWindow2(table,low,high);
24138 break;
24140 res = ddWindow3(table,low,high);
24141 break;
24143 res = ddWindow4(table,low,high);
24144 break;
24146 res = ddWindowConv2(table,low,high);
24147 break;
24149 res = ddWindowConv3(table,low,high);
24150 #ifdef DD_DEBUG
24151 supposedOpt = table->keys - table->isolated;
24152 res = ddWindow3(table,low,high);
24153 if (table->keys - table->isolated != (unsigned) supposedOpt) {
24154 (void) fprintf(table->err, "Convergence failed! (%d != %d)\n",
24155 table->keys - table->isolated, supposedOpt);
24156 }
24157 #endif
24158 break;
24160 res = ddWindowConv4(table,low,high);
24161 #ifdef DD_DEBUG
24162 supposedOpt = table->keys - table->isolated;
24163 res = ddWindow4(table,low,high);
24164 if (table->keys - table->isolated != (unsigned) supposedOpt) {
24165 (void) fprintf(table->err,"Convergence failed! (%d != %d)\n",
24166 table->keys - table->isolated, supposedOpt);
24167 }
24168 #endif
24169 break;
24170 default: return(0);
24171 }
24172 
24173 return(res);
24174 
24175 } /* end of cuddWindowReorder */
24176 
24177 
24178 /*---------------------------------------------------------------------------*/
24179 /* Definition of static functions */
24180 /*---------------------------------------------------------------------------*/
24181 
24194 static int
24196 DdManager * table,
24197 int low,
24198 int high)
24199 {
24200 
24201 int x;
24202 int res;
24203 int size;
24204 
24205 #ifdef DD_DEBUG
24206 assert(low >= 0 && high < table->size);
24207 #endif
24208 
24209 if (high-low < 1) return(0);
24210 
24211 res = table->keys - table->isolated;
24212 for (x = low; x < high; x++) {
24213 size = res;
24214 res = cuddSwapInPlace(table,x,x+1);
24215 if (res == 0) return(0);
24216 if (res >= size) { /* no improvement: undo permutation */
24217 res = cuddSwapInPlace(table,x,x+1);
24218 if (res == 0) return(0);
24219 }
24220 #ifdef DD_STATS
24221 if (res < size) {
24222 (void) fprintf(table->out,"-");
24223 } else {
24224 (void) fprintf(table->out,"=");
24225 }
24226 fflush(table->out);
24227 #endif
24228 }
24229 
24230 return(1);
24231 
24232 } /* end of ddWindow2 */
24233 
24234 
24248 static int
24250 DdManager * table,
24251 int low,
24252 int high)
24253 {
24254 int x;
24255 int res;
24256 int nwin;
24257 int newevent;
24258 int *events;
24259 int size;
24260 
24261 #ifdef DD_DEBUG
24262 assert(low >= 0 && high < table->size);
24263 #endif
24264 
24265 if (high-low < 1) return(ddWindowConv2(table,low,high));
24266 
24267 nwin = high-low;
24268 events = ALLOC(int,nwin);
24269 if (events == NULL) {
24270 table->errorCode = CUDD_MEMORY_OUT;
24271 return(0);
24272 }
24273 for (x=0; x<nwin; x++) {
24274 events[x] = 1;
24275 }
24276 
24277 res = table->keys - table->isolated;
24278 do {
24279 newevent = 0;
24280 for (x=0; x<nwin; x++) {
24281 if (events[x]) {
24282 size = res;
24283 res = cuddSwapInPlace(table,x+low,x+low+1);
24284 if (res == 0) {
24285 FREE(events);
24286 return(0);
24287 }
24288 if (res >= size) { /* no improvement: undo permutation */
24289 res = cuddSwapInPlace(table,x+low,x+low+1);
24290 if (res == 0) {
24291 FREE(events);
24292 return(0);
24293 }
24294 }
24295 if (res < size) {
24296 if (x < nwin-1) events[x+1] = 1;
24297 if (x > 0) events[x-1] = 1;
24298 newevent = 1;
24299 }
24300 events[x] = 0;
24301 #ifdef DD_STATS
24302 if (res < size) {
24303 (void) fprintf(table->out,"-");
24304 } else {
24305 (void) fprintf(table->out,"=");
24306 }
24307 fflush(table->out);
24308 #endif
24309 }
24310 }
24311 #ifdef DD_STATS
24312 if (newevent) {
24313 (void) fprintf(table->out,"|");
24314 fflush(table->out);
24315 }
24316 #endif
24317 } while (newevent);
24318 
24319 FREE(events);
24320 
24321 return(1);
24322 
24323 } /* end of ddWindowConv3 */
24324 
24325 
24341 static int
24343 DdManager * table,
24344 int x)
24345 {
24346 int y,z;
24347 int size,sizeNew;
24348 int best;
24349 
24350 #ifdef DD_DEBUG
24351 assert(table->dead == 0);
24352 assert(x+2 < table->size);
24353 #endif
24354 
24355 size = table->keys - table->isolated;
24356 y = x+1; z = y+1;
24357 
24358 /* The permutation pattern is:
24359 ** (x,y)(y,z)
24360 ** repeated three times to get all 3! = 6 permutations.
24361 */
24362 #define ABC 1
24363 best = ABC;
24364 
24365 #define BAC 2
24366 sizeNew = cuddSwapInPlace(table,x,y);
24367 if (sizeNew < size) {
24368 if (sizeNew == 0) return(0);
24369 best = BAC;
24370 size = sizeNew;
24371 }
24372 #define BCA 3
24373 sizeNew = cuddSwapInPlace(table,y,z);
24374 if (sizeNew < size) {
24375 if (sizeNew == 0) return(0);
24376 best = BCA;
24377 size = sizeNew;
24378 }
24379 #define CBA 4
24380 sizeNew = cuddSwapInPlace(table,x,y);
24381 if (sizeNew < size) {
24382 if (sizeNew == 0) return(0);
24383 best = CBA;
24384 size = sizeNew;
24385 }
24386 #define CAB 5
24387 sizeNew = cuddSwapInPlace(table,y,z);
24388 if (sizeNew < size) {
24389 if (sizeNew == 0) return(0);
24390 best = CAB;
24391 size = sizeNew;
24392 }
24393 #define ACB 6
24394 sizeNew = cuddSwapInPlace(table,x,y);
24395 if (sizeNew < size) {
24396 if (sizeNew == 0) return(0);
24397 best = ACB;
24398 size = sizeNew;
24399 }
24400 
24401 /* Now take the shortest route to the best permuytation.
24402 ** The initial permutation is ACB.
24403 */
24404 switch(best) {
24405 case BCA: if (!cuddSwapInPlace(table,y,z)) return(0);
24406 case CBA: if (!cuddSwapInPlace(table,x,y)) return(0);
24407 case ABC: if (!cuddSwapInPlace(table,y,z)) return(0);
24408 case ACB: break;
24409 case BAC: if (!cuddSwapInPlace(table,y,z)) return(0);
24410 case CAB: if (!cuddSwapInPlace(table,x,y)) return(0);
24411 break;
24412 default: return(0);
24413 }
24414 
24415 #ifdef DD_DEBUG
24416 assert(table->keys - table->isolated == (unsigned) size);
24417 #endif
24418 
24419 return(best);
24420 
24421 } /* end of ddPermuteWindow3 */
24422 
24423 
24436 static int
24438 DdManager * table,
24439 int low,
24440 int high)
24441 {
24442 
24443 int x;
24444 int res;
24445 
24446 #ifdef DD_DEBUG
24447 assert(low >= 0 && high < table->size);
24448 #endif
24449 
24450 if (high-low < 2) return(ddWindow2(table,low,high));
24451 
24452 for (x = low; x+1 < high; x++) {
24453 res = ddPermuteWindow3(table,x);
24454 if (res == 0) return(0);
24455 #ifdef DD_STATS
24456 if (res == ABC) {
24457 (void) fprintf(table->out,"=");
24458 } else {
24459 (void) fprintf(table->out,"-");
24460 }
24461 fflush(table->out);
24462 #endif
24463 }
24464 
24465 return(1);
24466 
24467 } /* end of ddWindow3 */
24468 
24469 
24483 static int
24485 DdManager * table,
24486 int low,
24487 int high)
24488 {
24489 int x;
24490 int res;
24491 int nwin;
24492 int newevent;
24493 int *events;
24494 
24495 #ifdef DD_DEBUG
24496 assert(low >= 0 && high < table->size);
24497 #endif
24498 
24499 if (high-low < 2) return(ddWindowConv2(table,low,high));
24500 
24501 nwin = high-low-1;
24502 events = ALLOC(int,nwin);
24503 if (events == NULL) {
24504 table->errorCode = CUDD_MEMORY_OUT;
24505 return(0);
24506 }
24507 for (x=0; x<nwin; x++) {
24508 events[x] = 1;
24509 }
24510 
24511 do {
24512 newevent = 0;
24513 for (x=0; x<nwin; x++) {
24514 if (events[x]) {
24515 res = ddPermuteWindow3(table,x+low);
24516 switch (res) {
24517 case ABC:
24518 break;
24519 case BAC:
24520 if (x < nwin-1) events[x+1] = 1;
24521 if (x > 1) events[x-2] = 1;
24522 newevent = 1;
24523 break;
24524 case BCA:
24525 case CBA:
24526 case CAB:
24527 if (x < nwin-2) events[x+2] = 1;
24528 if (x < nwin-1) events[x+1] = 1;
24529 if (x > 0) events[x-1] = 1;
24530 if (x > 1) events[x-2] = 1;
24531 newevent = 1;
24532 break;
24533 case ACB:
24534 if (x < nwin-2) events[x+2] = 1;
24535 if (x > 0) events[x-1] = 1;
24536 newevent = 1;
24537 break;
24538 default:
24539 FREE(events);
24540 return(0);
24541 }
24542 events[x] = 0;
24543 #ifdef DD_STATS
24544 if (res == ABC) {
24545 (void) fprintf(table->out,"=");
24546 } else {
24547 (void) fprintf(table->out,"-");
24548 }
24549 fflush(table->out);
24550 #endif
24551 }
24552 }
24553 #ifdef DD_STATS
24554 if (newevent) {
24555 (void) fprintf(table->out,"|");
24556 fflush(table->out);
24557 }
24558 #endif
24559 } while (newevent);
24560 
24561 FREE(events);
24562 
24563 return(1);
24564 
24565 } /* end of ddWindowConv3 */
24566 
24567 
24581 static int
24583 DdManager * table,
24584 int w)
24585 {
24586 int x,y,z;
24587 int size,sizeNew;
24588 int best;
24589 
24590 #ifdef DD_DEBUG
24591 assert(table->dead == 0);
24592 assert(w+3 < table->size);
24593 #endif
24594 
24595 size = table->keys - table->isolated;
24596 x = w+1; y = x+1; z = y+1;
24597 
24598 /* The permutation pattern is:
24599  * (w,x)(y,z)(w,x)(x,y)
24600  * (y,z)(w,x)(y,z)(x,y)
24601  * repeated three times to get all 4! = 24 permutations.
24602  * This gives a hamiltonian circuit of Cayley's graph.
24603  * The codes to the permutation are assigned in topological order.
24604  * The permutations at lower distance from the final permutation are
24605  * assigned lower codes. This way we can choose, between
24606  * permutations that give the same size, one that requires the minimum
24607  * number of swaps from the final permutation of the hamiltonian circuit.
24608  * There is an exception to this rule: ABCD is given Code 1, to
24609  * avoid oscillation when convergence is sought.
24610  */
24611 #define ABCD 1
24612 best = ABCD;
24613 
24614 #define BACD 7
24615 sizeNew = cuddSwapInPlace(table,w,x);
24616 if (sizeNew < size) {
24617 if (sizeNew == 0) return(0);
24618 best = BACD;
24619 size = sizeNew;
24620 }
24621 #define BADC 13
24622 sizeNew = cuddSwapInPlace(table,y,z);
24623 if (sizeNew < size) {
24624 if (sizeNew == 0) return(0);
24625 best = BADC;
24626 size = sizeNew;
24627 }
24628 #define ABDC 8
24629 sizeNew = cuddSwapInPlace(table,w,x);
24630 if (sizeNew < size || (sizeNew == size && ABDC < best)) {
24631 if (sizeNew == 0) return(0);
24632 best = ABDC;
24633 size = sizeNew;
24634 }
24635 #define ADBC 14
24636 sizeNew = cuddSwapInPlace(table,x,y);
24637 if (sizeNew < size) {
24638 if (sizeNew == 0) return(0);
24639 best = ADBC;
24640 size = sizeNew;
24641 }
24642 #define ADCB 9
24643 sizeNew = cuddSwapInPlace(table,y,z);
24644 if (sizeNew < size || (sizeNew == size && ADCB < best)) {
24645 if (sizeNew == 0) return(0);
24646 best = ADCB;
24647 size = sizeNew;
24648 }
24649 #define DACB 15
24650 sizeNew = cuddSwapInPlace(table,w,x);
24651 if (sizeNew < size) {
24652 if (sizeNew == 0) return(0);
24653 best = DACB;
24654 size = sizeNew;
24655 }
24656 #define DABC 20
24657 sizeNew = cuddSwapInPlace(table,y,z);
24658 if (sizeNew < size) {
24659 if (sizeNew == 0) return(0);
24660 best = DABC;
24661 size = sizeNew;
24662 }
24663 #define DBAC 23
24664 sizeNew = cuddSwapInPlace(table,x,y);
24665 if (sizeNew < size) {
24666 if (sizeNew == 0) return(0);
24667 best = DBAC;
24668 size = sizeNew;
24669 }
24670 #define BDAC 19
24671 sizeNew = cuddSwapInPlace(table,w,x);
24672 if (sizeNew < size || (sizeNew == size && BDAC < best)) {
24673 if (sizeNew == 0) return(0);
24674 best = BDAC;
24675 size = sizeNew;
24676 }
24677 #define BDCA 21
24678 sizeNew = cuddSwapInPlace(table,y,z);
24679 if (sizeNew < size || (sizeNew == size && BDCA < best)) {
24680 if (sizeNew == 0) return(0);
24681 best = BDCA;
24682 size = sizeNew;
24683 }
24684 #define DBCA 24
24685 sizeNew = cuddSwapInPlace(table,w,x);
24686 if (sizeNew < size) {
24687 if (sizeNew == 0) return(0);
24688 best = DBCA;
24689 size = sizeNew;
24690 }
24691 #define DCBA 22
24692 sizeNew = cuddSwapInPlace(table,x,y);
24693 if (sizeNew < size || (sizeNew == size && DCBA < best)) {
24694 if (sizeNew == 0) return(0);
24695 best = DCBA;
24696 size = sizeNew;
24697 }
24698 #define DCAB 18
24699 sizeNew = cuddSwapInPlace(table,y,z);
24700 if (sizeNew < size || (sizeNew == size && DCAB < best)) {
24701 if (sizeNew == 0) return(0);
24702 best = DCAB;
24703 size = sizeNew;
24704 }
24705 #define CDAB 12
24706 sizeNew = cuddSwapInPlace(table,w,x);
24707 if (sizeNew < size || (sizeNew == size && CDAB < best)) {
24708 if (sizeNew == 0) return(0);
24709 best = CDAB;
24710 size = sizeNew;
24711 }
24712 #define CDBA 17
24713 sizeNew = cuddSwapInPlace(table,y,z);
24714 if (sizeNew < size || (sizeNew == size && CDBA < best)) {
24715 if (sizeNew == 0) return(0);
24716 best = CDBA;
24717 size = sizeNew;
24718 }
24719 #define CBDA 11
24720 sizeNew = cuddSwapInPlace(table,x,y);
24721 if (sizeNew < size || (sizeNew == size && CBDA < best)) {
24722 if (sizeNew == 0) return(0);
24723 best = CBDA;
24724 size = sizeNew;
24725 }
24726 #define BCDA 16
24727 sizeNew = cuddSwapInPlace(table,w,x);
24728 if (sizeNew < size || (sizeNew == size && BCDA < best)) {
24729 if (sizeNew == 0) return(0);
24730 best = BCDA;
24731 size = sizeNew;
24732 }
24733 #define BCAD 10
24734 sizeNew = cuddSwapInPlace(table,y,z);
24735 if (sizeNew < size || (sizeNew == size && BCAD < best)) {
24736 if (sizeNew == 0) return(0);
24737 best = BCAD;
24738 size = sizeNew;
24739 }
24740 #define CBAD 5
24741 sizeNew = cuddSwapInPlace(table,w,x);
24742 if (sizeNew < size || (sizeNew == size && CBAD < best)) {
24743 if (sizeNew == 0) return(0);
24744 best = CBAD;
24745 size = sizeNew;
24746 }
24747 #define CABD 3
24748 sizeNew = cuddSwapInPlace(table,x,y);
24749 if (sizeNew < size || (sizeNew == size && CABD < best)) {
24750 if (sizeNew == 0) return(0);
24751 best = CABD;
24752 size = sizeNew;
24753 }
24754 #define CADB 6
24755 sizeNew = cuddSwapInPlace(table,y,z);
24756 if (sizeNew < size || (sizeNew == size && CADB < best)) {
24757 if (sizeNew == 0) return(0);
24758 best = CADB;
24759 size = sizeNew;
24760 }
24761 #define ACDB 4
24762 sizeNew = cuddSwapInPlace(table,w,x);
24763 if (sizeNew < size || (sizeNew == size && ACDB < best)) {
24764 if (sizeNew == 0) return(0);
24765 best = ACDB;
24766 size = sizeNew;
24767 }
24768 #define ACBD 2
24769 sizeNew = cuddSwapInPlace(table,y,z);
24770 if (sizeNew < size || (sizeNew == size && ACBD < best)) {
24771 if (sizeNew == 0) return(0);
24772 best = ACBD;
24773 size = sizeNew;
24774 }
24775 
24776 /* Now take the shortest route to the best permutation.
24777 ** The initial permutation is ACBD.
24778 */
24779 switch(best) {
24780 case DBCA: if (!cuddSwapInPlace(table,y,z)) return(0);
24781 case BDCA: if (!cuddSwapInPlace(table,x,y)) return(0);
24782 case CDBA: if (!cuddSwapInPlace(table,w,x)) return(0);
24783 case ADBC: if (!cuddSwapInPlace(table,y,z)) return(0);
24784 case ABDC: if (!cuddSwapInPlace(table,x,y)) return(0);
24785 case ACDB: if (!cuddSwapInPlace(table,y,z)) return(0);
24786 case ACBD: break;
24787 case DCBA: if (!cuddSwapInPlace(table,y,z)) return(0);
24788 case BCDA: if (!cuddSwapInPlace(table,x,y)) return(0);
24789 case CBDA: if (!cuddSwapInPlace(table,w,x)) return(0);
24790 if (!cuddSwapInPlace(table,x,y)) return(0);
24791 if (!cuddSwapInPlace(table,y,z)) return(0);
24792 break;
24793 case DBAC: if (!cuddSwapInPlace(table,x,y)) return(0);
24794 case DCAB: if (!cuddSwapInPlace(table,w,x)) return(0);
24795 case DACB: if (!cuddSwapInPlace(table,y,z)) return(0);
24796 case BACD: if (!cuddSwapInPlace(table,x,y)) return(0);
24797 case CABD: if (!cuddSwapInPlace(table,w,x)) return(0);
24798 break;
24799 case DABC: if (!cuddSwapInPlace(table,y,z)) return(0);
24800 case BADC: if (!cuddSwapInPlace(table,x,y)) return(0);
24801 case CADB: if (!cuddSwapInPlace(table,w,x)) return(0);
24802 if (!cuddSwapInPlace(table,y,z)) return(0);
24803 break;
24804 case BDAC: if (!cuddSwapInPlace(table,x,y)) return(0);
24805 case CDAB: if (!cuddSwapInPlace(table,w,x)) return(0);
24806 case ADCB: if (!cuddSwapInPlace(table,y,z)) return(0);
24807 case ABCD: if (!cuddSwapInPlace(table,x,y)) return(0);
24808 break;
24809 case BCAD: if (!cuddSwapInPlace(table,x,y)) return(0);
24810 case CBAD: if (!cuddSwapInPlace(table,w,x)) return(0);
24811 if (!cuddSwapInPlace(table,x,y)) return(0);
24812 break;
24813 default: return(0);
24814 }
24815 
24816 #ifdef DD_DEBUG
24817 assert(table->keys - table->isolated == (unsigned) size);
24818 #endif
24819 
24820 return(best);
24821 
24822 } /* end of ddPermuteWindow4 */
24823 
24824 
24837 static int
24839 DdManager * table,
24840 int low,
24841 int high)
24842 {
24843 
24844 int w;
24845 int res;
24846 
24847 #ifdef DD_DEBUG
24848 assert(low >= 0 && high < table->size);
24849 #endif
24850 
24851 if (high-low < 3) return(ddWindow3(table,low,high));
24852 
24853 for (w = low; w+2 < high; w++) {
24854 res = ddPermuteWindow4(table,w);
24855 if (res == 0) return(0);
24856 #ifdef DD_STATS
24857 if (res == ABCD) {
24858 (void) fprintf(table->out,"=");
24859 } else {
24860 (void) fprintf(table->out,"-");
24861 }
24862 fflush(table->out);
24863 #endif
24864 }
24865 
24866 return(1);
24867 
24868 } /* end of ddWindow4 */
24869 
24870 
24884 static int
24886 DdManager * table,
24887 int low,
24888 int high)
24889 {
24890 int x;
24891 int res;
24892 int nwin;
24893 int newevent;
24894 int *events;
24895 
24896 #ifdef DD_DEBUG
24897 assert(low >= 0 && high < table->size);
24898 #endif
24899 
24900 if (high-low < 3) return(ddWindowConv3(table,low,high));
24901 
24902 nwin = high-low-2;
24903 events = ALLOC(int,nwin);
24904 if (events == NULL) {
24905 table->errorCode = CUDD_MEMORY_OUT;
24906 return(0);
24907 }
24908 for (x=0; x<nwin; x++) {
24909 events[x] = 1;
24910 }
24911 
24912 do {
24913 newevent = 0;
24914 for (x=0; x<nwin; x++) {
24915 if (events[x]) {
24916 res = ddPermuteWindow4(table,x+low);
24917 switch (res) {
24918 case ABCD:
24919 break;
24920 case BACD:
24921 if (x < nwin-1) events[x+1] = 1;
24922 if (x > 2) events[x-3] = 1;
24923 newevent = 1;
24924 break;
24925 case BADC:
24926 if (x < nwin-3) events[x+3] = 1;
24927 if (x < nwin-1) events[x+1] = 1;
24928 if (x > 0) events[x-1] = 1;
24929 if (x > 2) events[x-3] = 1;
24930 newevent = 1;
24931 break;
24932 case ABDC:
24933 if (x < nwin-3) events[x+3] = 1;
24934 if (x > 0) events[x-1] = 1;
24935 newevent = 1;
24936 break;
24937 case ADBC:
24938 case ADCB:
24939 case ACDB:
24940 if (x < nwin-3) events[x+3] = 1;
24941 if (x < nwin-2) events[x+2] = 1;
24942 if (x > 0) events[x-1] = 1;
24943 if (x > 1) events[x-2] = 1;
24944 newevent = 1;
24945 break;
24946 case DACB:
24947 case DABC:
24948 case DBAC:
24949 case BDAC:
24950 case BDCA:
24951 case DBCA:
24952 case DCBA:
24953 case DCAB:
24954 case CDAB:
24955 case CDBA:
24956 case CBDA:
24957 case BCDA:
24958 case CADB:
24959 if (x < nwin-3) events[x+3] = 1;
24960 if (x < nwin-2) events[x+2] = 1;
24961 if (x < nwin-1) events[x+1] = 1;
24962 if (x > 0) events[x-1] = 1;
24963 if (x > 1) events[x-2] = 1;
24964 if (x > 2) events[x-3] = 1;
24965 newevent = 1;
24966 break;
24967 case BCAD:
24968 case CBAD:
24969 case CABD:
24970 if (x < nwin-2) events[x+2] = 1;
24971 if (x < nwin-1) events[x+1] = 1;
24972 if (x > 1) events[x-2] = 1;
24973 if (x > 2) events[x-3] = 1;
24974 newevent = 1;
24975 break;
24976 case ACBD:
24977 if (x < nwin-2) events[x+2] = 1;
24978 if (x > 1) events[x-2] = 1;
24979 newevent = 1;
24980 break;
24981 default:
24982 FREE(events);
24983 return(0);
24984 }
24985 events[x] = 0;
24986 #ifdef DD_STATS
24987 if (res == ABCD) {
24988 (void) fprintf(table->out,"=");
24989 } else {
24990 (void) fprintf(table->out,"-");
24991 }
24992 fflush(table->out);
24993 #endif
24994 }
24995 }
24996 #ifdef DD_STATS
24997 if (newevent) {
24998 (void) fprintf(table->out,"|");
24999 fflush(table->out);
25000 }
25001 #endif
25002 } while (newevent);
25003 
25004 FREE(events);
25005 
25006 return(1);
25007 
25008 } /* end of ddWindowConv4 */
25087 /*---------------------------------------------------------------------------*/
25088 /* Constant declarations */
25089 /*---------------------------------------------------------------------------*/
25090 
25091 
25092 /*---------------------------------------------------------------------------*/
25093 /* Stucture declarations */
25094 /*---------------------------------------------------------------------------*/
25095 
25096 
25097 /*---------------------------------------------------------------------------*/
25098 /* Type declarations */
25099 /*---------------------------------------------------------------------------*/
25100 
25101 
25102 /*---------------------------------------------------------------------------*/
25103 /* Variable declarations */
25104 /*---------------------------------------------------------------------------*/
25105 
25106 //#ifndef lint
25107 //static char rcsid[] DD_UNUSED = "$Id: cuddZddFuncs.c,v 1.17 2012/02/05 01:07:19 fabio Exp $";
25108 //#endif
25109 
25110 /*---------------------------------------------------------------------------*/
25111 /* Macro declarations */
25112 /*---------------------------------------------------------------------------*/
25113 
25114 
25117 /*---------------------------------------------------------------------------*/
25118 /* Static function prototypes */
25119 /*---------------------------------------------------------------------------*/
25120 
25121 
25125 /*---------------------------------------------------------------------------*/
25126 /* Definition of exported functions */
25127 /*---------------------------------------------------------------------------*/
25128 
25129 
25130 /*---------------------------------------------------------------------------*/
25131 /* Definition of internal functions */
25132 /*---------------------------------------------------------------------------*/
25133 
25134 
25146 DdNode *
25148  DdManager * dd,
25149  DdNode * f,
25150  DdNode * g)
25151 {
25152  int v, top_f, top_g;
25153  DdNode *tmp, *term1, *term2, *term3;
25154  DdNode *f0, *f1, *fd, *g0, *g1, *gd;
25155  DdNode *R0, *R1, *Rd, *N0, *N1;
25156  DdNode *r;
25157  DdNode *one = DD_ONE(dd);
25158  DdNode *zero = DD_ZERO(dd);
25159  int flag;
25160  int pv, nv;
25161 
25162  statLine(dd);
25163  if (f == zero || g == zero)
25164  return(zero);
25165  if (f == one)
25166  return(g);
25167  if (g == one)
25168  return(f);
25169 
25170  top_f = dd->permZ[f->index];
25171  top_g = dd->permZ[g->index];
25172 
25173  if (top_f > top_g)
25174  return(cuddZddProduct(dd, g, f));
25175 
25176  /* Check cache */
25177  r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g);
25178  if (r)
25179  return(r);
25180 
25181  v = f->index; /* either yi or zi */
25182  flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
25183  if (flag == 1)
25184  return(NULL);
25185  Cudd_Ref(f1);
25186  Cudd_Ref(f0);
25187  Cudd_Ref(fd);
25188  flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
25189  if (flag == 1) {
25190  Cudd_RecursiveDerefZdd(dd, f1);
25191  Cudd_RecursiveDerefZdd(dd, f0);
25192  Cudd_RecursiveDerefZdd(dd, fd);
25193  return(NULL);
25194  }
25195  Cudd_Ref(g1);
25196  Cudd_Ref(g0);
25197  Cudd_Ref(gd);
25198  pv = cuddZddGetPosVarIndex(dd, v);
25199  nv = cuddZddGetNegVarIndex(dd, v);
25200 
25201  Rd = cuddZddProduct(dd, fd, gd);
25202  if (Rd == NULL) {
25203  Cudd_RecursiveDerefZdd(dd, f1);
25204  Cudd_RecursiveDerefZdd(dd, f0);
25205  Cudd_RecursiveDerefZdd(dd, fd);
25206  Cudd_RecursiveDerefZdd(dd, g1);
25207  Cudd_RecursiveDerefZdd(dd, g0);
25208  Cudd_RecursiveDerefZdd(dd, gd);
25209  return(NULL);
25210  }
25211  Cudd_Ref(Rd);
25212 
25213  term1 = cuddZddProduct(dd, f0, g0);
25214  if (term1 == NULL) {
25215  Cudd_RecursiveDerefZdd(dd, f1);
25216  Cudd_RecursiveDerefZdd(dd, f0);
25217  Cudd_RecursiveDerefZdd(dd, fd);
25218  Cudd_RecursiveDerefZdd(dd, g1);
25219  Cudd_RecursiveDerefZdd(dd, g0);
25220  Cudd_RecursiveDerefZdd(dd, gd);
25221  Cudd_RecursiveDerefZdd(dd, Rd);
25222  return(NULL);
25223  }
25224  Cudd_Ref(term1);
25225  term2 = cuddZddProduct(dd, f0, gd);
25226  if (term2 == NULL) {
25227  Cudd_RecursiveDerefZdd(dd, f1);
25228  Cudd_RecursiveDerefZdd(dd, f0);
25229  Cudd_RecursiveDerefZdd(dd, fd);
25230  Cudd_RecursiveDerefZdd(dd, g1);
25231  Cudd_RecursiveDerefZdd(dd, g0);
25232  Cudd_RecursiveDerefZdd(dd, gd);
25233  Cudd_RecursiveDerefZdd(dd, Rd);
25234  Cudd_RecursiveDerefZdd(dd, term1);
25235  return(NULL);
25236  }
25237  Cudd_Ref(term2);
25238  term3 = cuddZddProduct(dd, fd, g0);
25239  if (term3 == NULL) {
25240  Cudd_RecursiveDerefZdd(dd, f1);
25241  Cudd_RecursiveDerefZdd(dd, f0);
25242  Cudd_RecursiveDerefZdd(dd, fd);
25243  Cudd_RecursiveDerefZdd(dd, g1);
25244  Cudd_RecursiveDerefZdd(dd, g0);
25245  Cudd_RecursiveDerefZdd(dd, gd);
25246  Cudd_RecursiveDerefZdd(dd, Rd);
25247  Cudd_RecursiveDerefZdd(dd, term1);
25248  Cudd_RecursiveDerefZdd(dd, term2);
25249  return(NULL);
25250  }
25251  Cudd_Ref(term3);
25252  Cudd_RecursiveDerefZdd(dd, f0);
25253  Cudd_RecursiveDerefZdd(dd, g0);
25254  tmp = cuddZddUnion(dd, term1, term2);
25255  if (tmp == NULL) {
25256  Cudd_RecursiveDerefZdd(dd, f1);
25257  Cudd_RecursiveDerefZdd(dd, fd);
25258  Cudd_RecursiveDerefZdd(dd, g1);
25259  Cudd_RecursiveDerefZdd(dd, gd);
25260  Cudd_RecursiveDerefZdd(dd, Rd);
25261  Cudd_RecursiveDerefZdd(dd, term1);
25262  Cudd_RecursiveDerefZdd(dd, term2);
25263  Cudd_RecursiveDerefZdd(dd, term3);
25264  return(NULL);
25265  }
25266  Cudd_Ref(tmp);
25267  Cudd_RecursiveDerefZdd(dd, term1);
25268  Cudd_RecursiveDerefZdd(dd, term2);
25269  R0 = cuddZddUnion(dd, tmp, term3);
25270  if (R0 == NULL) {
25271  Cudd_RecursiveDerefZdd(dd, f1);
25272  Cudd_RecursiveDerefZdd(dd, fd);
25273  Cudd_RecursiveDerefZdd(dd, g1);
25274  Cudd_RecursiveDerefZdd(dd, gd);
25275  Cudd_RecursiveDerefZdd(dd, Rd);
25276  Cudd_RecursiveDerefZdd(dd, term3);
25277  Cudd_RecursiveDerefZdd(dd, tmp);
25278  return(NULL);
25279  }
25280  Cudd_Ref(R0);
25281  Cudd_RecursiveDerefZdd(dd, tmp);
25282  Cudd_RecursiveDerefZdd(dd, term3);
25283  N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */
25284  if (N0 == NULL) {
25285  Cudd_RecursiveDerefZdd(dd, f1);
25286  Cudd_RecursiveDerefZdd(dd, fd);
25287  Cudd_RecursiveDerefZdd(dd, g1);
25288  Cudd_RecursiveDerefZdd(dd, gd);
25289  Cudd_RecursiveDerefZdd(dd, Rd);
25290  Cudd_RecursiveDerefZdd(dd, R0);
25291  return(NULL);
25292  }
25293  Cudd_Ref(N0);
25294  Cudd_RecursiveDerefZdd(dd, R0);
25295  Cudd_RecursiveDerefZdd(dd, Rd);
25296 
25297  term1 = cuddZddProduct(dd, f1, g1);
25298  if (term1 == NULL) {
25299  Cudd_RecursiveDerefZdd(dd, f1);
25300  Cudd_RecursiveDerefZdd(dd, fd);
25301  Cudd_RecursiveDerefZdd(dd, g1);
25302  Cudd_RecursiveDerefZdd(dd, gd);
25303  Cudd_RecursiveDerefZdd(dd, N0);
25304  return(NULL);
25305  }
25306  Cudd_Ref(term1);
25307  term2 = cuddZddProduct(dd, f1, gd);
25308  if (term2 == NULL) {
25309  Cudd_RecursiveDerefZdd(dd, f1);
25310  Cudd_RecursiveDerefZdd(dd, fd);
25311  Cudd_RecursiveDerefZdd(dd, g1);
25312  Cudd_RecursiveDerefZdd(dd, gd);
25313  Cudd_RecursiveDerefZdd(dd, N0);
25314  Cudd_RecursiveDerefZdd(dd, term1);
25315  return(NULL);
25316  }
25317  Cudd_Ref(term2);
25318  term3 = cuddZddProduct(dd, fd, g1);
25319  if (term3 == NULL) {
25320  Cudd_RecursiveDerefZdd(dd, f1);
25321  Cudd_RecursiveDerefZdd(dd, fd);
25322  Cudd_RecursiveDerefZdd(dd, g1);
25323  Cudd_RecursiveDerefZdd(dd, gd);
25324  Cudd_RecursiveDerefZdd(dd, N0);
25325  Cudd_RecursiveDerefZdd(dd, term1);
25326  Cudd_RecursiveDerefZdd(dd, term2);
25327  return(NULL);
25328  }
25329  Cudd_Ref(term3);
25330  Cudd_RecursiveDerefZdd(dd, f1);
25331  Cudd_RecursiveDerefZdd(dd, g1);
25332  Cudd_RecursiveDerefZdd(dd, fd);
25333  Cudd_RecursiveDerefZdd(dd, gd);
25334  tmp = cuddZddUnion(dd, term1, term2);
25335  if (tmp == NULL) {
25336  Cudd_RecursiveDerefZdd(dd, N0);
25337  Cudd_RecursiveDerefZdd(dd, term1);
25338  Cudd_RecursiveDerefZdd(dd, term2);
25339  Cudd_RecursiveDerefZdd(dd, term3);
25340  return(NULL);
25341  }
25342  Cudd_Ref(tmp);
25343  Cudd_RecursiveDerefZdd(dd, term1);
25344  Cudd_RecursiveDerefZdd(dd, term2);
25345  R1 = cuddZddUnion(dd, tmp, term3);
25346  if (R1 == NULL) {
25347  Cudd_RecursiveDerefZdd(dd, N0);
25348  Cudd_RecursiveDerefZdd(dd, term3);
25349  Cudd_RecursiveDerefZdd(dd, tmp);
25350  return(NULL);
25351  }
25352  Cudd_Ref(R1);
25353  Cudd_RecursiveDerefZdd(dd, tmp);
25354  Cudd_RecursiveDerefZdd(dd, term3);
25355  N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */
25356  if (N1 == NULL) {
25357  Cudd_RecursiveDerefZdd(dd, N0);
25358  Cudd_RecursiveDerefZdd(dd, R1);
25359  return(NULL);
25360  }
25361  Cudd_Ref(N1);
25362  Cudd_RecursiveDerefZdd(dd, R1);
25363  Cudd_RecursiveDerefZdd(dd, N0);
25364 
25365  cuddCacheInsert2(dd, cuddZddProduct, f, g, N1);
25366  Cudd_Deref(N1);
25367  return(N1);
25368 
25369 } /* end of cuddZddProduct */
25370 
25371 
25383 DdNode *
25385  DdManager * dd,
25386  DdNode * f,
25387  DdNode * g)
25388 {
25389  int v, top_f, top_g;
25390  DdNode *term1, *term2, *term3, *term4;
25391  DdNode *sum1, *sum2;
25392  DdNode *f0, *f1, *g0, *g1;
25393  DdNode *r;
25394  DdNode *one = DD_ONE(dd);
25395  DdNode *zero = DD_ZERO(dd);
25396  int flag;
25397 
25398  statLine(dd);
25399  if (f == zero || g == zero)
25400  return(zero);
25401  if (f == one)
25402  return(g);
25403  if (g == one)
25404  return(f);
25405 
25406  top_f = dd->permZ[f->index];
25407  top_g = dd->permZ[g->index];
25408 
25409  if (top_f > top_g)
25410  return(cuddZddUnateProduct(dd, g, f));
25411 
25412  /* Check cache */
25414  if (r)
25415  return(r);
25416 
25417  v = f->index; /* either yi or zi */
25418  flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
25419  if (flag == 1)
25420  return(NULL);
25421  Cudd_Ref(f1);
25422  Cudd_Ref(f0);
25423  flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);
25424  if (flag == 1) {
25425  Cudd_RecursiveDerefZdd(dd, f1);
25426  Cudd_RecursiveDerefZdd(dd, f0);
25427  return(NULL);
25428  }
25429  Cudd_Ref(g1);
25430  Cudd_Ref(g0);
25431 
25432  term1 = cuddZddUnateProduct(dd, f1, g1);
25433  if (term1 == NULL) {
25434  Cudd_RecursiveDerefZdd(dd, f1);
25435  Cudd_RecursiveDerefZdd(dd, f0);
25436  Cudd_RecursiveDerefZdd(dd, g1);
25437  Cudd_RecursiveDerefZdd(dd, g0);
25438  return(NULL);
25439  }
25440  Cudd_Ref(term1);
25441  term2 = cuddZddUnateProduct(dd, f1, g0);
25442  if (term2 == NULL) {
25443  Cudd_RecursiveDerefZdd(dd, f1);
25444  Cudd_RecursiveDerefZdd(dd, f0);
25445  Cudd_RecursiveDerefZdd(dd, g1);
25446  Cudd_RecursiveDerefZdd(dd, g0);
25447  Cudd_RecursiveDerefZdd(dd, term1);
25448  return(NULL);
25449  }
25450  Cudd_Ref(term2);
25451  term3 = cuddZddUnateProduct(dd, f0, g1);
25452  if (term3 == NULL) {
25453  Cudd_RecursiveDerefZdd(dd, f1);
25454  Cudd_RecursiveDerefZdd(dd, f0);
25455  Cudd_RecursiveDerefZdd(dd, g1);
25456  Cudd_RecursiveDerefZdd(dd, g0);
25457  Cudd_RecursiveDerefZdd(dd, term1);
25458  Cudd_RecursiveDerefZdd(dd, term2);
25459  return(NULL);
25460  }
25461  Cudd_Ref(term3);
25462  term4 = cuddZddUnateProduct(dd, f0, g0);
25463  if (term4 == NULL) {
25464  Cudd_RecursiveDerefZdd(dd, f1);
25465  Cudd_RecursiveDerefZdd(dd, f0);
25466  Cudd_RecursiveDerefZdd(dd, g1);
25467  Cudd_RecursiveDerefZdd(dd, g0);
25468  Cudd_RecursiveDerefZdd(dd, term1);
25469  Cudd_RecursiveDerefZdd(dd, term2);
25470  Cudd_RecursiveDerefZdd(dd, term3);
25471  return(NULL);
25472  }
25473  Cudd_Ref(term4);
25474  Cudd_RecursiveDerefZdd(dd, f1);
25475  Cudd_RecursiveDerefZdd(dd, f0);
25476  Cudd_RecursiveDerefZdd(dd, g1);
25477  Cudd_RecursiveDerefZdd(dd, g0);
25478  sum1 = cuddZddUnion(dd, term1, term2);
25479  if (sum1 == NULL) {
25480  Cudd_RecursiveDerefZdd(dd, term1);
25481  Cudd_RecursiveDerefZdd(dd, term2);
25482  Cudd_RecursiveDerefZdd(dd, term3);
25483  Cudd_RecursiveDerefZdd(dd, term4);
25484  return(NULL);
25485  }
25486  Cudd_Ref(sum1);
25487  Cudd_RecursiveDerefZdd(dd, term1);
25488  Cudd_RecursiveDerefZdd(dd, term2);
25489  sum2 = cuddZddUnion(dd, sum1, term3);
25490  if (sum2 == NULL) {
25491  Cudd_RecursiveDerefZdd(dd, term3);
25492  Cudd_RecursiveDerefZdd(dd, term4);
25493  Cudd_RecursiveDerefZdd(dd, sum1);
25494  return(NULL);
25495  }
25496  Cudd_Ref(sum2);
25497  Cudd_RecursiveDerefZdd(dd, sum1);
25498  Cudd_RecursiveDerefZdd(dd, term3);
25499  r = cuddZddGetNode(dd, v, sum2, term4);
25500  if (r == NULL) {
25501  Cudd_RecursiveDerefZdd(dd, term4);
25502  Cudd_RecursiveDerefZdd(dd, sum2);
25503  return(NULL);
25504  }
25505  Cudd_Ref(r);
25506  Cudd_RecursiveDerefZdd(dd, sum2);
25507  Cudd_RecursiveDerefZdd(dd, term4);
25508 
25509  cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r);
25510  Cudd_Deref(r);
25511  return(r);
25512 
25513 } /* end of cuddZddUnateProduct */
25514 
25515 
25527 DdNode *
25529  DdManager * dd,
25530  DdNode * f,
25531  DdNode * g)
25532 {
25533  int v;
25534  DdNode *one = DD_ONE(dd);
25535  DdNode *zero = DD_ZERO(dd);
25536  DdNode *f0, *f1, *fd, *g0, *g1, *gd;
25537  DdNode *q, *tmp;
25538  DdNode *r;
25539  int flag;
25540 
25541  statLine(dd);
25542  if (g == one)
25543  return(f);
25544  if (f == zero || f == one)
25545  return(zero);
25546  if (f == g)
25547  return(one);
25548 
25549  /* Check cache. */
25550  r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g);
25551  if (r)
25552  return(r);
25553 
25554  v = g->index;
25555 
25556  flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
25557  if (flag == 1)
25558  return(NULL);
25559  Cudd_Ref(f1);
25560  Cudd_Ref(f0);
25561  Cudd_Ref(fd);
25562  flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
25563  if (flag == 1) {
25564  Cudd_RecursiveDerefZdd(dd, f1);
25565  Cudd_RecursiveDerefZdd(dd, f0);
25566  Cudd_RecursiveDerefZdd(dd, fd);
25567  return(NULL);
25568  }
25569  Cudd_Ref(g1);
25570  Cudd_Ref(g0);
25571  Cudd_Ref(gd);
25572 
25573  q = g;
25574 
25575  if (g0 != zero) {
25576  q = cuddZddWeakDiv(dd, f0, g0);
25577  if (q == NULL) {
25578  Cudd_RecursiveDerefZdd(dd, f1);
25579  Cudd_RecursiveDerefZdd(dd, f0);
25580  Cudd_RecursiveDerefZdd(dd, fd);
25581  Cudd_RecursiveDerefZdd(dd, g1);
25582  Cudd_RecursiveDerefZdd(dd, g0);
25583  Cudd_RecursiveDerefZdd(dd, gd);
25584  return(NULL);
25585  }
25586  Cudd_Ref(q);
25587  }
25588  else
25589  Cudd_Ref(q);
25590  Cudd_RecursiveDerefZdd(dd, f0);
25591  Cudd_RecursiveDerefZdd(dd, g0);
25592 
25593  if (q == zero) {
25594  Cudd_RecursiveDerefZdd(dd, f1);
25595  Cudd_RecursiveDerefZdd(dd, g1);
25596  Cudd_RecursiveDerefZdd(dd, fd);
25597  Cudd_RecursiveDerefZdd(dd, gd);
25598  cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
25599  Cudd_Deref(q);
25600  return(zero);
25601  }
25602 
25603  if (g1 != zero) {
25604  Cudd_RecursiveDerefZdd(dd, q);
25605  tmp = cuddZddWeakDiv(dd, f1, g1);
25606  if (tmp == NULL) {
25607  Cudd_RecursiveDerefZdd(dd, f1);
25608  Cudd_RecursiveDerefZdd(dd, g1);
25609  Cudd_RecursiveDerefZdd(dd, fd);
25610  Cudd_RecursiveDerefZdd(dd, gd);
25611  return(NULL);
25612  }
25613  Cudd_Ref(tmp);
25614  Cudd_RecursiveDerefZdd(dd, f1);
25615  Cudd_RecursiveDerefZdd(dd, g1);
25616  if (q == g)
25617  q = tmp;
25618  else {
25619  q = cuddZddIntersect(dd, q, tmp);
25620  if (q == NULL) {
25621  Cudd_RecursiveDerefZdd(dd, fd);
25622  Cudd_RecursiveDerefZdd(dd, gd);
25623  return(NULL);
25624  }
25625  Cudd_Ref(q);
25626  Cudd_RecursiveDerefZdd(dd, tmp);
25627  }
25628  }
25629  else {
25630  Cudd_RecursiveDerefZdd(dd, f1);
25631  Cudd_RecursiveDerefZdd(dd, g1);
25632  }
25633 
25634  if (q == zero) {
25635  Cudd_RecursiveDerefZdd(dd, fd);
25636  Cudd_RecursiveDerefZdd(dd, gd);
25637  cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
25638  Cudd_Deref(q);
25639  return(zero);
25640  }
25641 
25642  if (gd != zero) {
25643  Cudd_RecursiveDerefZdd(dd, q);
25644  tmp = cuddZddWeakDiv(dd, fd, gd);
25645  if (tmp == NULL) {
25646  Cudd_RecursiveDerefZdd(dd, fd);
25647  Cudd_RecursiveDerefZdd(dd, gd);
25648  return(NULL);
25649  }
25650  Cudd_Ref(tmp);
25651  Cudd_RecursiveDerefZdd(dd, fd);
25652  Cudd_RecursiveDerefZdd(dd, gd);
25653  if (q == g)
25654  q = tmp;
25655  else {
25656  q = cuddZddIntersect(dd, q, tmp);
25657  if (q == NULL) {
25658  Cudd_RecursiveDerefZdd(dd, tmp);
25659  return(NULL);
25660  }
25661  Cudd_Ref(q);
25662  Cudd_RecursiveDerefZdd(dd, tmp);
25663  }
25664  }
25665  else {
25666  Cudd_RecursiveDerefZdd(dd, fd);
25667  Cudd_RecursiveDerefZdd(dd, gd);
25668  }
25669 
25670  cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q);
25671  Cudd_Deref(q);
25672  return(q);
25673 
25674 } /* end of cuddZddWeakDiv */
25675 
25676 
25688 DdNode *
25690  DdManager * dd,
25691  DdNode * f,
25692  DdNode * g)
25693 {
25694  int v, top_f, top_g, vf, vg;
25695  DdNode *one = DD_ONE(dd);
25696  DdNode *zero = DD_ZERO(dd);
25697  DdNode *f0, *f1, *fd, *g0, *g1, *gd;
25698  DdNode *q, *tmp;
25699  DdNode *r;
25700  DdNode *term1, *term0, *termd;
25701  int flag;
25702  int pv, nv;
25703 
25704  statLine(dd);
25705  if (g == one)
25706  return(f);
25707  if (f == zero || f == one)
25708  return(zero);
25709  if (f == g)
25710  return(one);
25711 
25712  /* Check cache. */
25713  r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g);
25714  if (r)
25715  return(r);
25716 
25717  top_f = dd->permZ[f->index];
25718  top_g = dd->permZ[g->index];
25719  vf = top_f >> 1;
25720  vg = top_g >> 1;
25721  v = ddMin(top_f, top_g);
25722 
25723  if (v == top_f && vf < vg) {
25724  v = f->index;
25725  flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
25726  if (flag == 1)
25727  return(NULL);
25728  Cudd_Ref(f1);
25729  Cudd_Ref(f0);
25730  Cudd_Ref(fd);
25731 
25732  pv = cuddZddGetPosVarIndex(dd, v);
25733  nv = cuddZddGetNegVarIndex(dd, v);
25734 
25735  term1 = cuddZddWeakDivF(dd, f1, g);
25736  if (term1 == NULL) {
25737  Cudd_RecursiveDerefZdd(dd, f1);
25738  Cudd_RecursiveDerefZdd(dd, f0);
25739  Cudd_RecursiveDerefZdd(dd, fd);
25740  return(NULL);
25741  }
25742  Cudd_Ref(term1);
25743  Cudd_RecursiveDerefZdd(dd, f1);
25744  term0 = cuddZddWeakDivF(dd, f0, g);
25745  if (term0 == NULL) {
25746  Cudd_RecursiveDerefZdd(dd, f0);
25747  Cudd_RecursiveDerefZdd(dd, fd);
25748  Cudd_RecursiveDerefZdd(dd, term1);
25749  return(NULL);
25750  }
25751  Cudd_Ref(term0);
25752  Cudd_RecursiveDerefZdd(dd, f0);
25753  termd = cuddZddWeakDivF(dd, fd, g);
25754  if (termd == NULL) {
25755  Cudd_RecursiveDerefZdd(dd, fd);
25756  Cudd_RecursiveDerefZdd(dd, term1);
25757  Cudd_RecursiveDerefZdd(dd, term0);
25758  return(NULL);
25759  }
25760  Cudd_Ref(termd);
25761  Cudd_RecursiveDerefZdd(dd, fd);
25762 
25763  tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */
25764  if (tmp == NULL) {
25765  Cudd_RecursiveDerefZdd(dd, term1);
25766  Cudd_RecursiveDerefZdd(dd, term0);
25767  Cudd_RecursiveDerefZdd(dd, termd);
25768  return(NULL);
25769  }
25770  Cudd_Ref(tmp);
25771  Cudd_RecursiveDerefZdd(dd, term0);
25772  Cudd_RecursiveDerefZdd(dd, termd);
25773  q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */
25774  if (q == NULL) {
25775  Cudd_RecursiveDerefZdd(dd, term1);
25776  Cudd_RecursiveDerefZdd(dd, tmp);
25777  return(NULL);
25778  }
25779  Cudd_Ref(q);
25780  Cudd_RecursiveDerefZdd(dd, term1);
25781  Cudd_RecursiveDerefZdd(dd, tmp);
25782 
25783  cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
25784  Cudd_Deref(q);
25785  return(q);
25786  }
25787 
25788  if (v == top_f)
25789  v = f->index;
25790  else
25791  v = g->index;
25792 
25793  flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
25794  if (flag == 1)
25795  return(NULL);
25796  Cudd_Ref(f1);
25797  Cudd_Ref(f0);
25798  Cudd_Ref(fd);
25799  flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
25800  if (flag == 1) {
25801  Cudd_RecursiveDerefZdd(dd, f1);
25802  Cudd_RecursiveDerefZdd(dd, f0);
25803  Cudd_RecursiveDerefZdd(dd, fd);
25804  return(NULL);
25805  }
25806  Cudd_Ref(g1);
25807  Cudd_Ref(g0);
25808  Cudd_Ref(gd);
25809 
25810  q = g;
25811 
25812  if (g0 != zero) {
25813  q = cuddZddWeakDivF(dd, f0, g0);
25814  if (q == NULL) {
25815  Cudd_RecursiveDerefZdd(dd, f1);
25816  Cudd_RecursiveDerefZdd(dd, f0);
25817  Cudd_RecursiveDerefZdd(dd, fd);
25818  Cudd_RecursiveDerefZdd(dd, g1);
25819  Cudd_RecursiveDerefZdd(dd, g0);
25820  Cudd_RecursiveDerefZdd(dd, gd);
25821  return(NULL);
25822  }
25823  Cudd_Ref(q);
25824  }
25825  else
25826  Cudd_Ref(q);
25827  Cudd_RecursiveDerefZdd(dd, f0);
25828  Cudd_RecursiveDerefZdd(dd, g0);
25829 
25830  if (q == zero) {
25831  Cudd_RecursiveDerefZdd(dd, f1);
25832  Cudd_RecursiveDerefZdd(dd, g1);
25833  Cudd_RecursiveDerefZdd(dd, fd);
25834  Cudd_RecursiveDerefZdd(dd, gd);
25835  cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
25836  Cudd_Deref(q);
25837  return(zero);
25838  }
25839 
25840  if (g1 != zero) {
25841  Cudd_RecursiveDerefZdd(dd, q);
25842  tmp = cuddZddWeakDivF(dd, f1, g1);
25843  if (tmp == NULL) {
25844  Cudd_RecursiveDerefZdd(dd, f1);
25845  Cudd_RecursiveDerefZdd(dd, g1);
25846  Cudd_RecursiveDerefZdd(dd, fd);
25847  Cudd_RecursiveDerefZdd(dd, gd);
25848  return(NULL);
25849  }
25850  Cudd_Ref(tmp);
25851  Cudd_RecursiveDerefZdd(dd, f1);
25852  Cudd_RecursiveDerefZdd(dd, g1);
25853  if (q == g)
25854  q = tmp;
25855  else {
25856  q = cuddZddIntersect(dd, q, tmp);
25857  if (q == NULL) {
25858  Cudd_RecursiveDerefZdd(dd, fd);
25859  Cudd_RecursiveDerefZdd(dd, gd);
25860  return(NULL);
25861  }
25862  Cudd_Ref(q);
25863  Cudd_RecursiveDerefZdd(dd, tmp);
25864  }
25865  }
25866  else {
25867  Cudd_RecursiveDerefZdd(dd, f1);
25868  Cudd_RecursiveDerefZdd(dd, g1);
25869  }
25870 
25871  if (q == zero) {
25872  Cudd_RecursiveDerefZdd(dd, fd);
25873  Cudd_RecursiveDerefZdd(dd, gd);
25874  cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
25875  Cudd_Deref(q);
25876  return(zero);
25877  }
25878 
25879  if (gd != zero) {
25880  Cudd_RecursiveDerefZdd(dd, q);
25881  tmp = cuddZddWeakDivF(dd, fd, gd);
25882  if (tmp == NULL) {
25883  Cudd_RecursiveDerefZdd(dd, fd);
25884  Cudd_RecursiveDerefZdd(dd, gd);
25885  return(NULL);
25886  }
25887  Cudd_Ref(tmp);
25888  Cudd_RecursiveDerefZdd(dd, fd);
25889  Cudd_RecursiveDerefZdd(dd, gd);
25890  if (q == g)
25891  q = tmp;
25892  else {
25893  q = cuddZddIntersect(dd, q, tmp);
25894  if (q == NULL) {
25895  Cudd_RecursiveDerefZdd(dd, tmp);
25896  return(NULL);
25897  }
25898  Cudd_Ref(q);
25899  Cudd_RecursiveDerefZdd(dd, tmp);
25900  }
25901  }
25902  else {
25903  Cudd_RecursiveDerefZdd(dd, fd);
25904  Cudd_RecursiveDerefZdd(dd, gd);
25905  }
25906 
25907  cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
25908  Cudd_Deref(q);
25909  return(q);
25910 
25911 } /* end of cuddZddWeakDivF */
25912 
25913 
25925 DdNode *
25927  DdManager * dd,
25928  DdNode * f,
25929  DdNode * g)
25930 {
25931  int v;
25932  DdNode *one = DD_ONE(dd);
25933  DdNode *zero = DD_ZERO(dd);
25934  DdNode *f0, *f1, *g0, *g1;
25935  DdNode *q, *r, *tmp;
25936  int flag;
25937 
25938  statLine(dd);
25939  if (g == one)
25940  return(f);
25941  if (f == zero || f == one)
25942  return(zero);
25943  if (f == g)
25944  return(one);
25945 
25946  /* Check cache. */
25947  r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g);
25948  if (r)
25949  return(r);
25950 
25951  v = g->index;
25952 
25953  flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
25954  if (flag == 1)
25955  return(NULL);
25956  Cudd_Ref(f1);
25957  Cudd_Ref(f0);
25958  flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */
25959  if (flag == 1) {
25960  Cudd_RecursiveDerefZdd(dd, f1);
25961  Cudd_RecursiveDerefZdd(dd, f0);
25962  return(NULL);
25963  }
25964  Cudd_Ref(g1);
25965  Cudd_Ref(g0);
25966 
25967  r = cuddZddDivide(dd, f1, g1);
25968  if (r == NULL) {
25969  Cudd_RecursiveDerefZdd(dd, f1);
25970  Cudd_RecursiveDerefZdd(dd, f0);
25971  Cudd_RecursiveDerefZdd(dd, g1);
25972  Cudd_RecursiveDerefZdd(dd, g0);
25973  return(NULL);
25974  }
25975  Cudd_Ref(r);
25976 
25977  if (r != zero && g0 != zero) {
25978  tmp = r;
25979  q = cuddZddDivide(dd, f0, g0);
25980  if (q == NULL) {
25981  Cudd_RecursiveDerefZdd(dd, f1);
25982  Cudd_RecursiveDerefZdd(dd, f0);
25983  Cudd_RecursiveDerefZdd(dd, g1);
25984  Cudd_RecursiveDerefZdd(dd, g0);
25985  return(NULL);
25986  }
25987  Cudd_Ref(q);
25988  r = cuddZddIntersect(dd, r, q);
25989  if (r == NULL) {
25990  Cudd_RecursiveDerefZdd(dd, f1);
25991  Cudd_RecursiveDerefZdd(dd, f0);
25992  Cudd_RecursiveDerefZdd(dd, g1);
25993  Cudd_RecursiveDerefZdd(dd, g0);
25994  Cudd_RecursiveDerefZdd(dd, q);
25995  return(NULL);
25996  }
25997  Cudd_Ref(r);
25998  Cudd_RecursiveDerefZdd(dd, q);
25999  Cudd_RecursiveDerefZdd(dd, tmp);
26000  }
26001 
26002  Cudd_RecursiveDerefZdd(dd, f1);
26003  Cudd_RecursiveDerefZdd(dd, f0);
26004  Cudd_RecursiveDerefZdd(dd, g1);
26005  Cudd_RecursiveDerefZdd(dd, g0);
26006 
26007  cuddCacheInsert2(dd, cuddZddDivide, f, g, r);
26008  Cudd_Deref(r);
26009  return(r);
26010 
26011 } /* end of cuddZddDivide */
26012 
26013 
26025 DdNode *
26027  DdManager * dd,
26028  DdNode * f,
26029  DdNode * g)
26030 {
26031  int v;
26032  DdNode *one = DD_ONE(dd);
26033  DdNode *zero = DD_ZERO(dd);
26034  DdNode *f0, *f1, *g0, *g1;
26035  DdNode *q, *r, *tmp;
26036  int flag;
26037 
26038  statLine(dd);
26039  if (g == one)
26040  return(f);
26041  if (f == zero || f == one)
26042  return(zero);
26043  if (f == g)
26044  return(one);
26045 
26046  /* Check cache. */
26047  r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g);
26048  if (r)
26049  return(r);
26050 
26051  v = g->index;
26052 
26053  flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
26054  if (flag == 1)
26055  return(NULL);
26056  Cudd_Ref(f1);
26057  Cudd_Ref(f0);
26058  flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */
26059  if (flag == 1) {
26060  Cudd_RecursiveDerefZdd(dd, f1);
26061  Cudd_RecursiveDerefZdd(dd, f0);
26062  return(NULL);
26063  }
26064  Cudd_Ref(g1);
26065  Cudd_Ref(g0);
26066 
26067  r = cuddZddDivideF(dd, f1, g1);
26068  if (r == NULL) {
26069  Cudd_RecursiveDerefZdd(dd, f1);
26070  Cudd_RecursiveDerefZdd(dd, f0);
26071  Cudd_RecursiveDerefZdd(dd, g1);
26072  Cudd_RecursiveDerefZdd(dd, g0);
26073  return(NULL);
26074  }
26075  Cudd_Ref(r);
26076 
26077  if (r != zero && g0 != zero) {
26078  tmp = r;
26079  q = cuddZddDivideF(dd, f0, g0);
26080  if (q == NULL) {
26081  Cudd_RecursiveDerefZdd(dd, f1);
26082  Cudd_RecursiveDerefZdd(dd, f0);
26083  Cudd_RecursiveDerefZdd(dd, g1);
26084  Cudd_RecursiveDerefZdd(dd, g0);
26085  return(NULL);
26086  }
26087  Cudd_Ref(q);
26088  r = cuddZddIntersect(dd, r, q);
26089  if (r == NULL) {
26090  Cudd_RecursiveDerefZdd(dd, f1);
26091  Cudd_RecursiveDerefZdd(dd, f0);
26092  Cudd_RecursiveDerefZdd(dd, g1);
26093  Cudd_RecursiveDerefZdd(dd, g0);
26094  Cudd_RecursiveDerefZdd(dd, q);
26095  return(NULL);
26096  }
26097  Cudd_Ref(r);
26098  Cudd_RecursiveDerefZdd(dd, q);
26099  Cudd_RecursiveDerefZdd(dd, tmp);
26100  }
26101 
26102  Cudd_RecursiveDerefZdd(dd, f1);
26103  Cudd_RecursiveDerefZdd(dd, f0);
26104  Cudd_RecursiveDerefZdd(dd, g1);
26105  Cudd_RecursiveDerefZdd(dd, g0);
26106 
26107  cuddCacheInsert2(dd, cuddZddDivideF, f, g, r);
26108  Cudd_Deref(r);
26109  return(r);
26110 
26111 } /* end of cuddZddDivideF */
26112 
26113 
26126 int
26128  DdManager * dd,
26129  DdNode * f,
26130  int v,
26131  DdNode ** f1,
26132  DdNode ** f0,
26133  DdNode ** fd)
26134 {
26135  DdNode *pc, *nc;
26136  DdNode *zero = DD_ZERO(dd);
26137  int top, hv, ht, pv, nv;
26138  int level;
26139 
26140  top = dd->permZ[f->index];
26141  level = dd->permZ[v];
26142  hv = level >> 1;
26143  ht = top >> 1;
26144 
26145  if (hv < ht) {
26146  *f1 = zero;
26147  *f0 = zero;
26148  *fd = f;
26149  }
26150  else {
26151  pv = cuddZddGetPosVarIndex(dd, v);
26152  nv = cuddZddGetNegVarIndex(dd, v);
26153 
26154  /* not to create intermediate ZDD node */
26155  if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) {
26156  pc = cuddZddSubset1(dd, f, pv);
26157  if (pc == NULL)
26158  return(1);
26159  Cudd_Ref(pc);
26160  nc = cuddZddSubset0(dd, f, pv);
26161  if (nc == NULL) {
26162  Cudd_RecursiveDerefZdd(dd, pc);
26163  return(1);
26164  }
26165  Cudd_Ref(nc);
26166 
26167  *f1 = cuddZddSubset0(dd, pc, nv);
26168  if (*f1 == NULL) {
26169  Cudd_RecursiveDerefZdd(dd, pc);
26170  Cudd_RecursiveDerefZdd(dd, nc);
26171  return(1);
26172  }
26173  Cudd_Ref(*f1);
26174  *f0 = cuddZddSubset1(dd, nc, nv);
26175  if (*f0 == NULL) {
26176  Cudd_RecursiveDerefZdd(dd, pc);
26177  Cudd_RecursiveDerefZdd(dd, nc);
26178  Cudd_RecursiveDerefZdd(dd, *f1);
26179  return(1);
26180  }
26181  Cudd_Ref(*f0);
26182 
26183  *fd = cuddZddSubset0(dd, nc, nv);
26184  if (*fd == NULL) {
26185  Cudd_RecursiveDerefZdd(dd, pc);
26186  Cudd_RecursiveDerefZdd(dd, nc);
26187  Cudd_RecursiveDerefZdd(dd, *f1);
26188  Cudd_RecursiveDerefZdd(dd, *f0);
26189  return(1);
26190  }
26191  Cudd_Ref(*fd);
26192  } else {
26193  pc = cuddZddSubset1(dd, f, nv);
26194  if (pc == NULL)
26195  return(1);
26196  Cudd_Ref(pc);
26197  nc = cuddZddSubset0(dd, f, nv);
26198  if (nc == NULL) {
26199  Cudd_RecursiveDerefZdd(dd, pc);
26200  return(1);
26201  }
26202  Cudd_Ref(nc);
26203 
26204  *f0 = cuddZddSubset0(dd, pc, pv);
26205  if (*f0 == NULL) {
26206  Cudd_RecursiveDerefZdd(dd, pc);
26207  Cudd_RecursiveDerefZdd(dd, nc);
26208  return(1);
26209  }
26210  Cudd_Ref(*f0);
26211  *f1 = cuddZddSubset1(dd, nc, pv);
26212  if (*f1 == NULL) {
26213  Cudd_RecursiveDerefZdd(dd, pc);
26214  Cudd_RecursiveDerefZdd(dd, nc);
26215  Cudd_RecursiveDerefZdd(dd, *f0);
26216  return(1);
26217  }
26218  Cudd_Ref(*f1);
26219 
26220  *fd = cuddZddSubset0(dd, nc, pv);
26221  if (*fd == NULL) {
26222  Cudd_RecursiveDerefZdd(dd, pc);
26223  Cudd_RecursiveDerefZdd(dd, nc);
26224  Cudd_RecursiveDerefZdd(dd, *f1);
26225  Cudd_RecursiveDerefZdd(dd, *f0);
26226  return(1);
26227  }
26228  Cudd_Ref(*fd);
26229  }
26230 
26231  Cudd_RecursiveDerefZdd(dd, pc);
26232  Cudd_RecursiveDerefZdd(dd, nc);
26233  Cudd_Deref(*f1);
26234  Cudd_Deref(*f0);
26235  Cudd_Deref(*fd);
26236  }
26237  return(0);
26238 
26239 } /* end of cuddZddGetCofactors3 */
26240 
26241 
26253 int
26255  DdManager * dd,
26256  DdNode * f,
26257  int v,
26258  DdNode ** f1,
26259  DdNode ** f0)
26260 {
26261  *f1 = cuddZddSubset1(dd, f, v);
26262  if (*f1 == NULL)
26263  return(1);
26264  *f0 = cuddZddSubset0(dd, f, v);
26265  if (*f0 == NULL) {
26266  Cudd_RecursiveDerefZdd(dd, *f1);
26267  return(1);
26268  }
26269  return(0);
26270 
26271 } /* end of cuddZddGetCofactors2 */
26272 
26273 
26288 DdNode *
26290  DdManager * dd,
26291  DdNode *node)
26292 {
26293  DdNode *b, *isop, *zdd_I;
26294 
26295  /* Check cache */
26296  zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node);
26297  if (zdd_I)
26298  return(zdd_I);
26299 
26300  b = cuddMakeBddFromZddCover(dd, node);
26301  if (!b)
26302  return(NULL);
26303  cuddRef(b);
26304  isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I);
26305  if (!isop) {
26306  Cudd_RecursiveDeref(dd, b);
26307  return(NULL);
26308  }
26309  cuddRef(isop);
26310  cuddRef(zdd_I);
26311  Cudd_RecursiveDeref(dd, b);
26312  Cudd_RecursiveDeref(dd, isop);
26313 
26314  cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I);
26315  cuddDeref(zdd_I);
26316  return(zdd_I);
26317 } /* end of cuddZddComplement */
26318 
26319 
26331 int
26333  DdManager * dd,
26334  int index)
26335 {
26336  int pv = (index >> 1) << 1;
26337  return(pv);
26338 } /* end of cuddZddGetPosVarIndex */
26339 
26340 
26352 int
26354  DdManager * dd,
26355  int index)
26356 {
26357  int nv = index | 0x1;
26358  return(nv);
26359 } /* end of cuddZddGetPosVarIndex */
26360 
26361 
26373 int
26375  DdManager * dd,
26376  int index)
26377 {
26378  int pv = cuddZddGetPosVarIndex(dd, index);
26379  return(dd->permZ[pv]);
26380 } /* end of cuddZddGetPosVarLevel */
26381 
26382 
26394 int
26396  DdManager * dd,
26397  int index)
26398 {
26399  int nv = cuddZddGetNegVarIndex(dd, index);
26400  return(dd->permZ[nv]);
26401 } /* end of cuddZddGetNegVarLevel */
26472 /*---------------------------------------------------------------------------*/
26473 /* Constant declarations */
26474 /*---------------------------------------------------------------------------*/
26475 
26476 /*---------------------------------------------------------------------------*/
26477 /* Stucture declarations */
26478 /*---------------------------------------------------------------------------*/
26479 
26480 /*---------------------------------------------------------------------------*/
26481 /* Type declarations */
26482 /*---------------------------------------------------------------------------*/
26483 
26484 /*---------------------------------------------------------------------------*/
26485 /* Variable declarations */
26486 /*---------------------------------------------------------------------------*/
26487 
26488 //#ifndef lint
26489 //static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.22 2012/02/05 01:07:19 fabio Exp $";
26490 //#endif
26491 
26492 static int *entry;
26493 extern int zddTotalNumberSwapping;
26494 #ifdef DD_STATS
26495 static int extsymmcalls;
26496 static int extsymm;
26497 static int secdiffcalls;
26498 static int secdiff;
26499 static int secdiffmisfire;
26500 #endif
26501 #ifdef DD_DEBUG
26502 static int pr = 0; /* flag to enable printing while debugging */
26503  /* by depositing a 1 into it */
26504 #endif
26505 
26506 /*---------------------------------------------------------------------------*/
26507 /* Macro declarations */
26508 /*---------------------------------------------------------------------------*/
26509 
26512 /*---------------------------------------------------------------------------*/
26513 /* Static function prototypes */
26514 /*---------------------------------------------------------------------------*/
26515 
26516 static int zddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
26517 #ifdef DD_STATS
26518 static int zddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
26519 #endif
26520 static int zddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
26521 static void zddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
26522 static int zddUniqueCompareGroup (int *ptrX, int *ptrY);
26523 static int zddGroupSifting (DdManager *table, int lower, int upper);
26524 static int zddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh);
26525 static int zddGroupSiftingUp (DdManager *table, int y, int xLow, Move **moves);
26526 static int zddGroupSiftingDown (DdManager *table, int x, int xHigh, Move **moves);
26527 static int zddGroupMove (DdManager *table, int x, int y, Move **moves);
26528 static int zddGroupMoveBackward (DdManager *table, int x, int y);
26529 static int zddGroupSiftingBackward (DdManager *table, Move *moves, int size);
26530 static void zddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
26531 
26535 /*---------------------------------------------------------------------------*/
26536 /* Definition of exported functions */
26537 /*---------------------------------------------------------------------------*/
26538 
26539 /*---------------------------------------------------------------------------*/
26540 /* Definition of internal functions */
26541 /*---------------------------------------------------------------------------*/
26542 
26543 
26557 int
26559  DdManager * table /* DD table */,
26560  Cudd_ReorderingType method /* reordering method for the groups of leaves */)
26561 {
26562  int i;
26563  int nvars;
26564  int result;
26565  int tempTree;
26566 
26567  /* If no tree is provided we create a temporary one in which all
26568  ** variables are in a single group. After reordering this tree is
26569  ** destroyed.
26570  */
26571  tempTree = table->treeZ == NULL;
26572  if (tempTree) {
26573  table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
26574  table->treeZ->index = table->invpermZ[0];
26575  }
26576  nvars = table->sizeZ;
26577 
26578 #ifdef DD_DEBUG
26579  if (pr > 0 && !tempTree)
26580  (void) fprintf(table->out,"cuddZddTreeSifting:");
26581  Mtr_PrintGroups(table->treeZ,pr <= 0);
26582 #endif
26583 #if 0
26584  /* Debugging code. */
26585  if (table->tree && table->treeZ) {
26586  (void) fprintf(table->out,"\n");
26587  Mtr_PrintGroups(table->tree, 0);
26588  cuddPrintVarGroups(table,table->tree,0,0);
26589  for (i = 0; i < table->size; i++) {
26590  (void) fprintf(table->out,"%s%d",
26591  (i == 0) ? "" : ",", table->invperm[i]);
26592  }
26593  (void) fprintf(table->out,"\n");
26594  for (i = 0; i < table->size; i++) {
26595  (void) fprintf(table->out,"%s%d",
26596  (i == 0) ? "" : ",", table->perm[i]);
26597  }
26598  (void) fprintf(table->out,"\n\n");
26599  Mtr_PrintGroups(table->treeZ,0);
26600  cuddPrintVarGroups(table,table->treeZ,1,0);
26601  for (i = 0; i < table->sizeZ; i++) {
26602  (void) fprintf(table->out,"%s%d",
26603  (i == 0) ? "" : ",", table->invpermZ[i]);
26604  }
26605  (void) fprintf(table->out,"\n");
26606  for (i = 0; i < table->sizeZ; i++) {
26607  (void) fprintf(table->out,"%s%d",
26608  (i == 0) ? "" : ",", table->permZ[i]);
26609  }
26610  (void) fprintf(table->out,"\n");
26611  }
26612  /* End of debugging code. */
26613 #endif
26614 #ifdef DD_STATS
26615  extsymmcalls = 0;
26616  extsymm = 0;
26617  secdiffcalls = 0;
26618  secdiff = 0;
26619  secdiffmisfire = 0;
26620 
26621  (void) fprintf(table->out,"\n");
26622  if (!tempTree)
26623  (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n",
26624  zddCountInternalMtrNodes(table,table->treeZ));
26625 #endif
26626 
26627  /* Initialize the group of each subtable to itself. Initially
26628  ** there are no groups. Groups are created according to the tree
26629  ** structure in postorder fashion.
26630  */
26631  for (i = 0; i < nvars; i++)
26632  table->subtableZ[i].next = i;
26633 
26634  /* Reorder. */
26635  result = zddTreeSiftingAux(table, table->treeZ, method);
26636 
26637 #ifdef DD_STATS /* print stats */
26638  if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
26639  (table->groupcheck == CUDD_GROUP_CHECK7 ||
26640  table->groupcheck == CUDD_GROUP_CHECK5)) {
26641  (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
26642  (void) fprintf(table->out,"extsymm = %d",extsymm);
26643  }
26644  if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
26645  table->groupcheck == CUDD_GROUP_CHECK7) {
26646  (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
26647  (void) fprintf(table->out,"secdiff = %d\n",secdiff);
26648  (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
26649  }
26650 #endif
26651 
26652  if (tempTree)
26653  Cudd_FreeZddTree(table);
26654  return(result);
26655 
26656 } /* end of cuddZddTreeSifting */
26657 
26658 
26659 /*---------------------------------------------------------------------------*/
26660 /* Definition of static functions */
26661 /*---------------------------------------------------------------------------*/
26662 
26663 
26674 static int
26676  DdManager * table,
26677  MtrNode * treenode,
26678  Cudd_ReorderingType method)
26679 {
26680  MtrNode *auxnode;
26681  int res;
26682 
26683 #ifdef DD_DEBUG
26684  Mtr_PrintGroups(treenode,1);
26685 #endif
26686 
26687  auxnode = treenode;
26688  while (auxnode != NULL) {
26689  if (auxnode->child != NULL) {
26690  if (!zddTreeSiftingAux(table, auxnode->child, method))
26691  return(0);
26692  res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
26693  if (res == 0)
26694  return(0);
26695  } else if (auxnode->size > 1) {
26696  if (!zddReorderChildren(table, auxnode, method))
26697  return(0);
26698  }
26699  auxnode = auxnode->younger;
26700  }
26701 
26702  return(1);
26703 
26704 } /* end of zddTreeSiftingAux */
26705 
26706 
26707 #ifdef DD_STATS
26708 
26718 static int
26719 zddCountInternalMtrNodes(
26720  DdManager * table,
26721  MtrNode * treenode)
26722 {
26723  MtrNode *auxnode;
26724  int count,nodeCount;
26725 
26726 
26727  nodeCount = 0;
26728  auxnode = treenode;
26729  while (auxnode != NULL) {
26730  if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
26731  nodeCount++;
26732  count = zddCountInternalMtrNodes(table,auxnode->child);
26733  nodeCount += count;
26734  }
26735  auxnode = auxnode->younger;
26736  }
26737 
26738  return(nodeCount);
26739 
26740 } /* end of zddCountInternalMtrNodes */
26741 #endif
26742 
26743 
26758 static int
26760  DdManager * table,
26761  MtrNode * treenode,
26762  Cudd_ReorderingType method)
26763 {
26764  int lower;
26765  int upper;
26766  int result;
26767  unsigned int initialSize;
26768 
26769  zddFindNodeHiLo(table,treenode,&lower,&upper);
26770  /* If upper == -1 these variables do not exist yet. */
26771  if (upper == -1)
26772  return(1);
26773 
26774  if (treenode->flags == MTR_FIXED) {
26775  result = 1;
26776  } else {
26777 #ifdef DD_STATS
26778  (void) fprintf(table->out," ");
26779 #endif
26780  switch (method) {
26781  case CUDD_REORDER_RANDOM:
26783  result = cuddZddSwapping(table,lower,upper,method);
26784  break;
26785  case CUDD_REORDER_SIFT:
26786  result = cuddZddSifting(table,lower,upper);
26787  break;
26789  do {
26790  initialSize = table->keysZ;
26791  result = cuddZddSifting(table,lower,upper);
26792  if (initialSize <= table->keysZ)
26793  break;
26794 #ifdef DD_STATS
26795  else
26796  (void) fprintf(table->out,"\n");
26797 #endif
26798  } while (result != 0);
26799  break;
26801  result = cuddZddSymmSifting(table,lower,upper);
26802  break;
26804  result = cuddZddSymmSiftingConv(table,lower,upper);
26805  break;
26807  result = zddGroupSifting(table,lower,upper);
26808  break;
26809  case CUDD_REORDER_LINEAR:
26810  result = cuddZddLinearSifting(table,lower,upper);
26811  break;
26813  do {
26814  initialSize = table->keysZ;
26815  result = cuddZddLinearSifting(table,lower,upper);
26816  if (initialSize <= table->keysZ)
26817  break;
26818 #ifdef DD_STATS
26819  else
26820  (void) fprintf(table->out,"\n");
26821 #endif
26822  } while (result != 0);
26823  break;
26824  default:
26825  return(0);
26826  }
26827  }
26828 
26829  /* Create a single group for all the variables that were sifted,
26830  ** so that they will be treated as a single block by successive
26831  ** invocations of zddGroupSifting.
26832  */
26833  zddMergeGroups(table,treenode,lower,upper);
26834 
26835 #ifdef DD_DEBUG
26836  if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:");
26837 #endif
26838 
26839  return(result);
26840 
26841 } /* end of zddReorderChildren */
26842 
26843 
26859 static void
26861  DdManager * table,
26862  MtrNode * treenode,
26863  int * lower,
26864  int * upper)
26865 {
26866  int low;
26867  int high;
26868 
26869  /* Check whether no variables in this group already exist.
26870  ** If so, return immediately. The calling procedure will know from
26871  ** the values of upper that no reordering is needed.
26872  */
26873  if ((int) treenode->low >= table->sizeZ) {
26874  *lower = table->sizeZ;
26875  *upper = -1;
26876  return;
26877  }
26878 
26879  *lower = low = (unsigned int) table->permZ[treenode->index];
26880  high = (int) (low + treenode->size - 1);
26881 
26882  if (high >= table->sizeZ) {
26883  /* This is the case of a partially existing group. The aim is to
26884  ** reorder as many variables as safely possible. If the tree
26885  ** node is terminal, we just reorder the subset of the group
26886  ** that is currently in existence. If the group has
26887  ** subgroups, then we only reorder those subgroups that are
26888  ** fully instantiated. This way we avoid breaking up a group.
26889  */
26890  MtrNode *auxnode = treenode->child;
26891  if (auxnode == NULL) {
26892  *upper = (unsigned int) table->sizeZ - 1;
26893  } else {
26894  /* Search the subgroup that strands the table->sizeZ line.
26895  ** If the first group starts at 0 and goes past table->sizeZ
26896  ** upper will get -1, thus correctly signaling that no reordering
26897  ** should take place.
26898  */
26899  while (auxnode != NULL) {
26900  int thisLower = table->permZ[auxnode->low];
26901  int thisUpper = thisLower + auxnode->size - 1;
26902  if (thisUpper >= table->sizeZ && thisLower < table->sizeZ)
26903  *upper = (unsigned int) thisLower - 1;
26904  auxnode = auxnode->younger;
26905  }
26906  }
26907  } else {
26908  /* Normal case: All the variables of the group exist. */
26909  *upper = (unsigned int) high;
26910  }
26911 
26912 #ifdef DD_DEBUG
26913  /* Make sure that all variables in group are contiguous. */
26914  assert(treenode->size >= *upper - *lower + 1);
26915 #endif
26916 
26917  return;
26918 
26919 } /* end of zddFindNodeHiLo */
26920 
26921 
26934 static int
26936  int * ptrX,
26937  int * ptrY)
26938 {
26939 #if 0
26940  if (entry[*ptrY] == entry[*ptrX]) {
26941  return((*ptrX) - (*ptrY));
26942  }
26943 #endif
26944  return(entry[*ptrY] - entry[*ptrX]);
26945 
26946 } /* end of zddUniqueCompareGroup */
26947 
26948 
26962 static int
26964  DdManager * table,
26965  int lower,
26966  int upper)
26967 {
26968  int *var;
26969  int i,j,x,xInit;
26970  int nvars;
26971  int classes;
26972  int result;
26973  int *sifted;
26974 #ifdef DD_STATS
26975  unsigned previousSize;
26976 #endif
26977  int xindex;
26978 
26979  nvars = table->sizeZ;
26980 
26981  /* Order variables to sift. */
26982  entry = NULL;
26983  sifted = NULL;
26984  var = ALLOC(int,nvars);
26985  if (var == NULL) {
26986  table->errorCode = CUDD_MEMORY_OUT;
26987  goto zddGroupSiftingOutOfMem;
26988  }
26989  entry = ALLOC(int,nvars);
26990  if (entry == NULL) {
26991  table->errorCode = CUDD_MEMORY_OUT;
26992  goto zddGroupSiftingOutOfMem;
26993  }
26994  sifted = ALLOC(int,nvars);
26995  if (sifted == NULL) {
26996  table->errorCode = CUDD_MEMORY_OUT;
26997  goto zddGroupSiftingOutOfMem;
26998  }
26999 
27000  /* Here we consider only one representative for each group. */
27001  for (i = 0, classes = 0; i < nvars; i++) {
27002  sifted[i] = 0;
27003  x = table->permZ[i];
27004  if ((unsigned) x >= table->subtableZ[x].next) {
27005  entry[i] = table->subtableZ[x].keys;
27006  var[classes] = i;
27007  classes++;
27008  }
27009  }
27010 
27011  qsort((void *)var,classes,sizeof(int),(DD_QSFP)zddUniqueCompareGroup);
27012 
27013  /* Now sift. */
27014  for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
27015  if (zddTotalNumberSwapping >= table->siftMaxSwap)
27016  break;
27017  if (util_cpu_time() - table->startTime > table->timeLimit) {
27018  table->autoDynZ = 0; /* prevent further reordering */
27019  break;
27020  }
27021  xindex = var[i];
27022  if (sifted[xindex] == 1) /* variable already sifted as part of group */
27023  continue;
27024  x = table->permZ[xindex]; /* find current level of this variable */
27025  if (x < lower || x > upper)
27026  continue;
27027 #ifdef DD_STATS
27028  previousSize = table->keysZ;
27029 #endif
27030 #ifdef DD_DEBUG
27031  /* x is bottom of group */
27032  assert((unsigned) x >= table->subtableZ[x].next);
27033 #endif
27034  result = zddGroupSiftingAux(table,x,lower,upper);
27035  if (!result) goto zddGroupSiftingOutOfMem;
27036 
27037 #ifdef DD_STATS
27038  if (table->keysZ < previousSize) {
27039  (void) fprintf(table->out,"-");
27040  } else if (table->keysZ > previousSize) {
27041  (void) fprintf(table->out,"+");
27042  } else {
27043  (void) fprintf(table->out,"=");
27044  }
27045  fflush(table->out);
27046 #endif
27047 
27048  /* Mark variables in the group just sifted. */
27049  x = table->permZ[xindex];
27050  if ((unsigned) x != table->subtableZ[x].next) {
27051  xInit = x;
27052  do {
27053  j = table->invpermZ[x];
27054  sifted[j] = 1;
27055  x = table->subtableZ[x].next;
27056  } while (x != xInit);
27057  }
27058 
27059 #ifdef DD_DEBUG
27060  if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:");
27061 #endif
27062  } /* for */
27063 
27064  FREE(sifted);
27065  FREE(var);
27066  FREE(entry);
27067 
27068  return(1);
27069 
27070  zddGroupSiftingOutOfMem:
27071  if (entry != NULL) FREE(entry);
27072  if (var != NULL) FREE(var);
27073  if (sifted != NULL) FREE(sifted);
27074 
27075  return(0);
27076 
27077 } /* end of zddGroupSifting */
27078 
27079 
27095 static int
27097  DdManager * table,
27098  int x,
27099  int xLow,
27100  int xHigh)
27101 {
27102  Move *move;
27103  Move *moves; /* list of moves */
27104  int initialSize;
27105  int result;
27106 
27107 
27108 #ifdef DD_DEBUG
27109  if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
27110  assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */
27111 #endif
27112 
27113  initialSize = table->keysZ;
27114  moves = NULL;
27115 
27116  if (x == xLow) { /* Sift down */
27117 #ifdef DD_DEBUG
27118  /* x must be a singleton */
27119  assert((unsigned) x == table->subtableZ[x].next);
27120 #endif
27121  if (x == xHigh) return(1); /* just one variable */
27122 
27123  if (!zddGroupSiftingDown(table,x,xHigh,&moves))
27124  goto zddGroupSiftingAuxOutOfMem;
27125  /* at this point x == xHigh, unless early term */
27126 
27127  /* move backward and stop at best position */
27128  result = zddGroupSiftingBackward(table,moves,initialSize);
27129 #ifdef DD_DEBUG
27130  assert(table->keysZ <= (unsigned) initialSize);
27131 #endif
27132  if (!result) goto zddGroupSiftingAuxOutOfMem;
27133 
27134  } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */
27135 #ifdef DD_DEBUG
27136  /* x is bottom of group */
27137  assert((unsigned) x >= table->subtableZ[x].next);
27138 #endif
27139  /* Find top of x's group */
27140  x = table->subtableZ[x].next;
27141 
27142  if (!zddGroupSiftingUp(table,x,xLow,&moves))
27143  goto zddGroupSiftingAuxOutOfMem;
27144  /* at this point x == xLow, unless early term */
27145 
27146  /* move backward and stop at best position */
27147  result = zddGroupSiftingBackward(table,moves,initialSize);
27148 #ifdef DD_DEBUG
27149  assert(table->keysZ <= (unsigned) initialSize);
27150 #endif
27151  if (!result) goto zddGroupSiftingAuxOutOfMem;
27152 
27153  } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
27154  if (!zddGroupSiftingDown(table,x,xHigh,&moves))
27155  goto zddGroupSiftingAuxOutOfMem;
27156  /* at this point x == xHigh, unless early term */
27157 
27158  /* Find top of group */
27159  if (moves) {
27160  x = moves->y;
27161  }
27162  while ((unsigned) x < table->subtableZ[x].next)
27163  x = table->subtableZ[x].next;
27164  x = table->subtableZ[x].next;
27165 #ifdef DD_DEBUG
27166  /* x should be the top of a group */
27167  assert((unsigned) x <= table->subtableZ[x].next);
27168 #endif
27169 
27170  if (!zddGroupSiftingUp(table,x,xLow,&moves))
27171  goto zddGroupSiftingAuxOutOfMem;
27172 
27173  /* move backward and stop at best position */
27174  result = zddGroupSiftingBackward(table,moves,initialSize);
27175 #ifdef DD_DEBUG
27176  assert(table->keysZ <= (unsigned) initialSize);
27177 #endif
27178  if (!result) goto zddGroupSiftingAuxOutOfMem;
27179 
27180  } else { /* moving up first: shorter */
27181  /* Find top of x's group */
27182  x = table->subtableZ[x].next;
27183 
27184  if (!zddGroupSiftingUp(table,x,xLow,&moves))
27185  goto zddGroupSiftingAuxOutOfMem;
27186  /* at this point x == xHigh, unless early term */
27187 
27188  if (moves) {
27189  x = moves->x;
27190  }
27191  while ((unsigned) x < table->subtableZ[x].next)
27192  x = table->subtableZ[x].next;
27193 #ifdef DD_DEBUG
27194  /* x is bottom of a group */
27195  assert((unsigned) x >= table->subtableZ[x].next);
27196 #endif
27197 
27198  if (!zddGroupSiftingDown(table,x,xHigh,&moves))
27199  goto zddGroupSiftingAuxOutOfMem;
27200 
27201  /* move backward and stop at best position */
27202  result = zddGroupSiftingBackward(table,moves,initialSize);
27203 #ifdef DD_DEBUG
27204  assert(table->keysZ <= (unsigned) initialSize);
27205 #endif
27206  if (!result) goto zddGroupSiftingAuxOutOfMem;
27207  }
27208 
27209  while (moves != NULL) {
27210  move = moves->next;
27211  cuddDeallocMove(table, moves);
27212  moves = move;
27213  }
27214 
27215  return(1);
27216 
27217  zddGroupSiftingAuxOutOfMem:
27218  while (moves != NULL) {
27219  move = moves->next;
27220  cuddDeallocMove(table, moves);
27221  moves = move;
27222  }
27223 
27224  return(0);
27225 
27226 } /* end of zddGroupSiftingAux */
27227 
27228 
27244 static int
27246  DdManager * table,
27247  int y,
27248  int xLow,
27249  Move ** moves)
27250 {
27251  Move *move;
27252  int x;
27253  int size;
27254  int gxtop;
27255  int limitSize;
27256 
27257  limitSize = table->keysZ;
27258 
27259  x = cuddZddNextLow(table,y);
27260  while (x >= xLow) {
27261  gxtop = table->subtableZ[x].next;
27262  if (table->subtableZ[x].next == (unsigned) x &&
27263  table->subtableZ[y].next == (unsigned) y) {
27264  /* x and y are self groups */
27265  size = cuddZddSwapInPlace(table,x,y);
27266 #ifdef DD_DEBUG
27267  assert(table->subtableZ[x].next == (unsigned) x);
27268  assert(table->subtableZ[y].next == (unsigned) y);
27269 #endif
27270  if (size == 0) goto zddGroupSiftingUpOutOfMem;
27271  move = (Move *)cuddDynamicAllocNode(table);
27272  if (move == NULL) goto zddGroupSiftingUpOutOfMem;
27273  move->x = x;
27274  move->y = y;
27275  move->flags = MTR_DEFAULT;
27276  move->size = size;
27277  move->next = *moves;
27278  *moves = move;
27279 
27280 #ifdef DD_DEBUG
27281  if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
27282 #endif
27283  if ((double) size > (double) limitSize * table->maxGrowth)
27284  return(1);
27285  if (size < limitSize) limitSize = size;
27286  } else { /* group move */
27287  size = zddGroupMove(table,x,y,moves);
27288  if (size == 0) goto zddGroupSiftingUpOutOfMem;
27289  if ((double) size > (double) limitSize * table->maxGrowth)
27290  return(1);
27291  if (size < limitSize) limitSize = size;
27292  }
27293  y = gxtop;
27294  x = cuddZddNextLow(table,y);
27295  }
27296 
27297  return(1);
27298 
27299  zddGroupSiftingUpOutOfMem:
27300  while (*moves != NULL) {
27301  move = (*moves)->next;
27302  cuddDeallocMove(table, *moves);
27303  *moves = move;
27304  }
27305  return(0);
27306 
27307 } /* end of zddGroupSiftingUp */
27308 
27309 
27321 static int
27323  DdManager * table,
27324  int x,
27325  int xHigh,
27326  Move ** moves)
27327 {
27328  Move *move;
27329  int y;
27330  int size;
27331  int limitSize;
27332  int gybot;
27333 
27334 
27335  /* Initialize R */
27336  limitSize = size = table->keysZ;
27337  y = cuddZddNextHigh(table,x);
27338  while (y <= xHigh) {
27339  /* Find bottom of y group. */
27340  gybot = table->subtableZ[y].next;
27341  while (table->subtableZ[gybot].next != (unsigned) y)
27342  gybot = table->subtableZ[gybot].next;
27343 
27344  if (table->subtableZ[x].next == (unsigned) x &&
27345  table->subtableZ[y].next == (unsigned) y) {
27346  /* x and y are self groups */
27347  size = cuddZddSwapInPlace(table,x,y);
27348 #ifdef DD_DEBUG
27349  assert(table->subtableZ[x].next == (unsigned) x);
27350  assert(table->subtableZ[y].next == (unsigned) y);
27351 #endif
27352  if (size == 0) goto zddGroupSiftingDownOutOfMem;
27353 
27354  /* Record move. */
27355  move = (Move *) cuddDynamicAllocNode(table);
27356  if (move == NULL) goto zddGroupSiftingDownOutOfMem;
27357  move->x = x;
27358  move->y = y;
27359  move->flags = MTR_DEFAULT;
27360  move->size = size;
27361  move->next = *moves;
27362  *moves = move;
27363 
27364 #ifdef DD_DEBUG
27365  if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n");
27366 #endif
27367  if ((double) size > (double) limitSize * table->maxGrowth)
27368  return(1);
27369  if (size < limitSize) limitSize = size;
27370  x = y;
27371  y = cuddZddNextHigh(table,x);
27372  } else { /* Group move */
27373  size = zddGroupMove(table,x,y,moves);
27374  if (size == 0) goto zddGroupSiftingDownOutOfMem;
27375  if ((double) size > (double) limitSize * table->maxGrowth)
27376  return(1);
27377  if (size < limitSize) limitSize = size;
27378  }
27379  x = gybot;
27380  y = cuddZddNextHigh(table,x);
27381  }
27382 
27383  return(1);
27384 
27385  zddGroupSiftingDownOutOfMem:
27386  while (*moves != NULL) {
27387  move = (*moves)->next;
27388  cuddDeallocMove(table, *moves);
27389  *moves = move;
27390  }
27391 
27392  return(0);
27393 
27394 } /* end of zddGroupSiftingDown */
27395 
27396 
27407 static int
27409  DdManager * table,
27410  int x,
27411  int y,
27412  Move ** moves)
27413 {
27414  Move *move;
27415  int size;
27416  int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
27417  int swapx,swapy;
27418 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
27419  int initialSize,bestSize;
27420 #endif
27421 
27422 #ifdef DD_DEBUG
27423  /* We assume that x < y */
27424  assert(x < y);
27425 #endif
27426  /* Find top, bottom, and size for the two groups. */
27427  xbot = x;
27428  xtop = table->subtableZ[x].next;
27429  xsize = xbot - xtop + 1;
27430  ybot = y;
27431  while ((unsigned) ybot < table->subtableZ[ybot].next)
27432  ybot = table->subtableZ[ybot].next;
27433  ytop = y;
27434  ysize = ybot - ytop + 1;
27435 
27436 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
27437  initialSize = bestSize = table->keysZ;
27438 #endif
27439  /* Sift the variables of the second group up through the first group */
27440  for (i = 1; i <= ysize; i++) {
27441  for (j = 1; j <= xsize; j++) {
27442  size = cuddZddSwapInPlace(table,x,y);
27443  if (size == 0) goto zddGroupMoveOutOfMem;
27444 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
27445  if (size < bestSize)
27446  bestSize = size;
27447 #endif
27448  swapx = x; swapy = y;
27449  y = x;
27450  x = cuddZddNextLow(table,y);
27451  }
27452  y = ytop + i;
27453  x = cuddZddNextLow(table,y);
27454  }
27455 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
27456  if ((bestSize < initialSize) && (bestSize < size))
27457  (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size);
27458 #endif
27459 
27460  /* fix groups */
27461  y = xtop; /* ytop is now where xtop used to be */
27462  for (i = 0; i < ysize - 1; i++) {
27463  table->subtableZ[y].next = cuddZddNextHigh(table,y);
27464  y = cuddZddNextHigh(table,y);
27465  }
27466  table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
27467  /* it to top of its group */
27468  x = cuddZddNextHigh(table,y);
27469  newxtop = x;
27470  for (i = 0; i < xsize - 1; i++) {
27471  table->subtableZ[x].next = cuddZddNextHigh(table,x);
27472  x = cuddZddNextHigh(table,x);
27473  }
27474  table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
27475  /* it to top of its group */
27476 #ifdef DD_DEBUG
27477  if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
27478 #endif
27479 
27480  /* Store group move */
27481  move = (Move *) cuddDynamicAllocNode(table);
27482  if (move == NULL) goto zddGroupMoveOutOfMem;
27483  move->x = swapx;
27484  move->y = swapy;
27485  move->flags = MTR_DEFAULT;
27486  move->size = table->keysZ;
27487  move->next = *moves;
27488  *moves = move;
27489 
27490  return(table->keysZ);
27491 
27492  zddGroupMoveOutOfMem:
27493  while (*moves != NULL) {
27494  move = (*moves)->next;
27495  cuddDeallocMove(table, *moves);
27496  *moves = move;
27497  }
27498  return(0);
27499 
27500 } /* end of zddGroupMove */
27501 
27502 
27513 static int
27515  DdManager * table,
27516  int x,
27517  int y)
27518 {
27519  int size;
27520  int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
27521 
27522 
27523 #ifdef DD_DEBUG
27524  /* We assume that x < y */
27525  assert(x < y);
27526 #endif
27527 
27528  /* Find top, bottom, and size for the two groups. */
27529  xbot = x;
27530  xtop = table->subtableZ[x].next;
27531  xsize = xbot - xtop + 1;
27532  ybot = y;
27533  while ((unsigned) ybot < table->subtableZ[ybot].next)
27534  ybot = table->subtableZ[ybot].next;
27535  ytop = y;
27536  ysize = ybot - ytop + 1;
27537 
27538  /* Sift the variables of the second group up through the first group */
27539  for (i = 1; i <= ysize; i++) {
27540  for (j = 1; j <= xsize; j++) {
27541  size = cuddZddSwapInPlace(table,x,y);
27542  if (size == 0)
27543  return(0);
27544  y = x;
27545  x = cuddZddNextLow(table,y);
27546  }
27547  y = ytop + i;
27548  x = cuddZddNextLow(table,y);
27549  }
27550 
27551  /* fix groups */
27552  y = xtop;
27553  for (i = 0; i < ysize - 1; i++) {
27554  table->subtableZ[y].next = cuddZddNextHigh(table,y);
27555  y = cuddZddNextHigh(table,y);
27556  }
27557  table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
27558  /* to its top */
27559  x = cuddZddNextHigh(table,y);
27560  newxtop = x;
27561  for (i = 0; i < xsize - 1; i++) {
27562  table->subtableZ[x].next = cuddZddNextHigh(table,x);
27563  x = cuddZddNextHigh(table,x);
27564  }
27565  table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
27566  /* to its top */
27567 #ifdef DD_DEBUG
27568  if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
27569 #endif
27570 
27571  return(1);
27572 
27573 } /* end of zddGroupMoveBackward */
27574 
27575 
27587 static int
27589  DdManager * table,
27590  Move * moves,
27591  int size)
27592 {
27593  Move *move;
27594  int res;
27595 
27596 
27597  for (move = moves; move != NULL; move = move->next) {
27598  if (move->size < size) {
27599  size = move->size;
27600  }
27601  }
27602 
27603  for (move = moves; move != NULL; move = move->next) {
27604  if (move->size == size) return(1);
27605  if ((table->subtableZ[move->x].next == move->x) &&
27606  (table->subtableZ[move->y].next == move->y)) {
27607  res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
27608  if (!res) return(0);
27609 #ifdef DD_DEBUG
27610  if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n");
27611  assert(table->subtableZ[move->x].next == move->x);
27612  assert(table->subtableZ[move->y].next == move->y);
27613 #endif
27614  } else { /* Group move necessary */
27615  res = zddGroupMoveBackward(table,(int)move->x,(int)move->y);
27616  if (!res) return(0);
27617  }
27618  }
27619 
27620  return(1);
27621 
27622 } /* end of zddGroupSiftingBackward */
27623 
27624 
27635 static void
27637  DdManager * table,
27638  MtrNode * treenode,
27639  int low,
27640  int high)
27641 {
27642  int i;
27643  MtrNode *auxnode;
27644  int saveindex;
27645  int newindex;
27646 
27647  /* Merge all variables from low to high in one group, unless
27648  ** this is the topmost group. In such a case we do not merge lest
27649  ** we lose the symmetry information. */
27650  if (treenode != table->treeZ) {
27651  for (i = low; i < high; i++)
27652  table->subtableZ[i].next = i+1;
27653  table->subtableZ[high].next = low;
27654  }
27655 
27656  /* Adjust the index fields of the tree nodes. If a node is the
27657  ** first child of its parent, then the parent may also need adjustment. */
27658  saveindex = treenode->index;
27659  newindex = table->invpermZ[low];
27660  auxnode = treenode;
27661  do {
27662  auxnode->index = newindex;
27663  if (auxnode->parent == NULL ||
27664  (int) auxnode->parent->index != saveindex)
27665  break;
27666  auxnode = auxnode->parent;
27667  } while (1);
27668  return;
27669 
27670 } /* end of zddMergeGroups */
27735 /*---------------------------------------------------------------------------*/
27736 /* Constant declarations */
27737 /*---------------------------------------------------------------------------*/
27738 
27739 
27740 /*---------------------------------------------------------------------------*/
27741 /* Stucture declarations */
27742 /*---------------------------------------------------------------------------*/
27743 
27744 
27745 /*---------------------------------------------------------------------------*/
27746 /* Type declarations */
27747 /*---------------------------------------------------------------------------*/
27748 
27749 
27750 /*---------------------------------------------------------------------------*/
27751 /* Variable declarations */
27752 /*---------------------------------------------------------------------------*/
27753 
27754 //#ifndef lint
27755 //static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.22 2012/02/05 01:07:19 fabio Exp $";
27756 //#endif
27757 
27758 /*---------------------------------------------------------------------------*/
27759 /* Macro declarations */
27760 /*---------------------------------------------------------------------------*/
27761 
27762 
27765 /*---------------------------------------------------------------------------*/
27766 /* Static function prototypes */
27767 /*---------------------------------------------------------------------------*/
27768 
27769 
27772 /*---------------------------------------------------------------------------*/
27773 /* Definition of exported functions */
27774 /*---------------------------------------------------------------------------*/
27775 
27776 
27777 /*---------------------------------------------------------------------------*/
27778 /* Definition of internal functions */
27779 /*---------------------------------------------------------------------------*/
27780 
27781 
27793 DdNode *
27795  DdManager * dd,
27796  DdNode * L,
27797  DdNode * U,
27798  DdNode ** zdd_I)
27799 {
27800  DdNode *one = DD_ONE(dd);
27801  DdNode *zero = Cudd_Not(one);
27802  DdNode *zdd_one = DD_ONE(dd);
27803  DdNode *zdd_zero = DD_ZERO(dd);
27804  int v, top_l, top_u;
27805  DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
27806  DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
27807  DdNode *Isub0, *Isub1, *Id;
27808  DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id;
27809  DdNode *x;
27810  DdNode *term0, *term1, *sum;
27811  DdNode *Lv, *Uv, *Lnv, *Unv;
27812  DdNode *r, *y, *z;
27813  int index;
27814  DD_CTFP cacheOp;
27815 
27816  statLine(dd);
27817  if (L == zero) {
27818  *zdd_I = zdd_zero;
27819  return(zero);
27820  }
27821  if (U == one) {
27822  *zdd_I = zdd_one;
27823  return(one);
27824  }
27825 
27826  if (U == zero || L == one) {
27827  printf("*** ERROR : illegal condition for ISOP (U < L).\n");
27828  exit(1);
27829  }
27830 
27831  /* Check the cache. We store two results for each recursive call.
27832  ** One is the BDD, and the other is the ZDD. Both are needed.
27833  ** Hence we need a double hit in the cache to terminate the
27834  ** recursion. Clearly, collisions may evict only one of the two
27835  ** results. */
27836  cacheOp = (DD_CTFP) cuddZddIsop;
27837  r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
27838  if (r) {
27839  *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U);
27840  if (*zdd_I)
27841  return(r);
27842  else {
27843  /* The BDD result may have been dead. In that case
27844  ** cuddCacheLookup2 would have called cuddReclaim,
27845  ** whose effects we now have to undo. */
27846  cuddRef(r);
27847  Cudd_RecursiveDeref(dd, r);
27848  }
27849  }
27850 
27851  top_l = dd->perm[Cudd_Regular(L)->index];
27852  top_u = dd->perm[Cudd_Regular(U)->index];
27853  v = ddMin(top_l, top_u);
27854 
27855  /* Compute cofactors. */
27856  if (top_l == v) {
27857  index = Cudd_Regular(L)->index;
27858  Lv = Cudd_T(L);
27859  Lnv = Cudd_E(L);
27860  if (Cudd_IsComplement(L)) {
27861  Lv = Cudd_Not(Lv);
27862  Lnv = Cudd_Not(Lnv);
27863  }
27864  }
27865  else {
27866  index = Cudd_Regular(U)->index;
27867  Lv = Lnv = L;
27868  }
27869 
27870  if (top_u == v) {
27871  Uv = Cudd_T(U);
27872  Unv = Cudd_E(U);
27873  if (Cudd_IsComplement(U)) {
27874  Uv = Cudd_Not(Uv);
27875  Unv = Cudd_Not(Unv);
27876  }
27877  }
27878  else {
27879  Uv = Unv = U;
27880  }
27881 
27882  Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
27883  if (Lsub0 == NULL)
27884  return(NULL);
27885  Cudd_Ref(Lsub0);
27886  Usub0 = Unv;
27887  Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
27888  if (Lsub1 == NULL) {
27889  Cudd_RecursiveDeref(dd, Lsub0);
27890  return(NULL);
27891  }
27892  Cudd_Ref(Lsub1);
27893  Usub1 = Uv;
27894 
27895  Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0);
27896  if (Isub0 == NULL) {
27897  Cudd_RecursiveDeref(dd, Lsub0);
27898  Cudd_RecursiveDeref(dd, Lsub1);
27899  return(NULL);
27900  }
27901  /*
27902  if ((!cuddIsConstant(Cudd_Regular(Isub0))) &&
27903  (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 ||
27904  dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) {
27905  printf("*** ERROR : illegal permutation in ZDD. ***\n");
27906  }
27907  */
27908  Cudd_Ref(Isub0);
27909  Cudd_Ref(zdd_Isub0);
27910  Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1);
27911  if (Isub1 == NULL) {
27912  Cudd_RecursiveDeref(dd, Lsub0);
27913  Cudd_RecursiveDeref(dd, Lsub1);
27914  Cudd_RecursiveDeref(dd, Isub0);
27915  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
27916  return(NULL);
27917  }
27918  /*
27919  if ((!cuddIsConstant(Cudd_Regular(Isub1))) &&
27920  (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 ||
27921  dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) {
27922  printf("*** ERROR : illegal permutation in ZDD. ***\n");
27923  }
27924  */
27925  Cudd_Ref(Isub1);
27926  Cudd_Ref(zdd_Isub1);
27927  Cudd_RecursiveDeref(dd, Lsub0);
27928  Cudd_RecursiveDeref(dd, Lsub1);
27929 
27930  Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
27931  if (Lsuper0 == NULL) {
27932  Cudd_RecursiveDeref(dd, Isub0);
27933  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
27934  Cudd_RecursiveDeref(dd, Isub1);
27935  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
27936  return(NULL);
27937  }
27938  Cudd_Ref(Lsuper0);
27939  Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
27940  if (Lsuper1 == NULL) {
27941  Cudd_RecursiveDeref(dd, Isub0);
27942  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
27943  Cudd_RecursiveDeref(dd, Isub1);
27944  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
27945  Cudd_RecursiveDeref(dd, Lsuper0);
27946  return(NULL);
27947  }
27948  Cudd_Ref(Lsuper1);
27949  Usuper0 = Unv;
27950  Usuper1 = Uv;
27951 
27952  /* Ld = Lsuper0 + Lsuper1 */
27953  Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
27954  if (Ld == NULL) {
27955  Cudd_RecursiveDeref(dd, Isub0);
27956  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
27957  Cudd_RecursiveDeref(dd, Isub1);
27958  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
27959  Cudd_RecursiveDeref(dd, Lsuper0);
27960  Cudd_RecursiveDeref(dd, Lsuper1);
27961  return(NULL);
27962  }
27963  Ld = Cudd_Not(Ld);
27964  Cudd_Ref(Ld);
27965  /* Ud = Usuper0 * Usuper1 */
27966  Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
27967  if (Ud == NULL) {
27968  Cudd_RecursiveDeref(dd, Isub0);
27969  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
27970  Cudd_RecursiveDeref(dd, Isub1);
27971  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
27972  Cudd_RecursiveDeref(dd, Lsuper0);
27973  Cudd_RecursiveDeref(dd, Lsuper1);
27974  Cudd_RecursiveDeref(dd, Ld);
27975  return(NULL);
27976  }
27977  Cudd_Ref(Ud);
27978  Cudd_RecursiveDeref(dd, Lsuper0);
27979  Cudd_RecursiveDeref(dd, Lsuper1);
27980 
27981  Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id);
27982  if (Id == NULL) {
27983  Cudd_RecursiveDeref(dd, Isub0);
27984  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
27985  Cudd_RecursiveDeref(dd, Isub1);
27986  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
27987  Cudd_RecursiveDeref(dd, Ld);
27988  Cudd_RecursiveDeref(dd, Ud);
27989  return(NULL);
27990  }
27991  /*
27992  if ((!cuddIsConstant(Cudd_Regular(Id))) &&
27993  (Cudd_Regular(Id)->index != zdd_Id->index / 2 ||
27994  dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) {
27995  printf("*** ERROR : illegal permutation in ZDD. ***\n");
27996  }
27997  */
27998  Cudd_Ref(Id);
27999  Cudd_Ref(zdd_Id);
28000  Cudd_RecursiveDeref(dd, Ld);
28001  Cudd_RecursiveDeref(dd, Ud);
28002 
28003  x = cuddUniqueInter(dd, index, one, zero);
28004  if (x == NULL) {
28005  Cudd_RecursiveDeref(dd, Isub0);
28006  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
28007  Cudd_RecursiveDeref(dd, Isub1);
28008  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
28009  Cudd_RecursiveDeref(dd, Id);
28010  Cudd_RecursiveDerefZdd(dd, zdd_Id);
28011  return(NULL);
28012  }
28013  Cudd_Ref(x);
28014  /* term0 = x * Isub0 */
28015  term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
28016  if (term0 == NULL) {
28017  Cudd_RecursiveDeref(dd, Isub0);
28018  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
28019  Cudd_RecursiveDeref(dd, Isub1);
28020  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
28021  Cudd_RecursiveDeref(dd, Id);
28022  Cudd_RecursiveDerefZdd(dd, zdd_Id);
28023  Cudd_RecursiveDeref(dd, x);
28024  return(NULL);
28025  }
28026  Cudd_Ref(term0);
28027  Cudd_RecursiveDeref(dd, Isub0);
28028  /* term1 = x * Isub1 */
28029  term1 = cuddBddAndRecur(dd, x, Isub1);
28030  if (term1 == NULL) {
28031  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
28032  Cudd_RecursiveDeref(dd, Isub1);
28033  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
28034  Cudd_RecursiveDeref(dd, Id);
28035  Cudd_RecursiveDerefZdd(dd, zdd_Id);
28036  Cudd_RecursiveDeref(dd, x);
28037  Cudd_RecursiveDeref(dd, term0);
28038  return(NULL);
28039  }
28040  Cudd_Ref(term1);
28041  Cudd_RecursiveDeref(dd, x);
28042  Cudd_RecursiveDeref(dd, Isub1);
28043  /* sum = term0 + term1 */
28044  sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
28045  if (sum == NULL) {
28046  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
28047  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
28048  Cudd_RecursiveDeref(dd, Id);
28049  Cudd_RecursiveDerefZdd(dd, zdd_Id);
28050  Cudd_RecursiveDeref(dd, term0);
28051  Cudd_RecursiveDeref(dd, term1);
28052  return(NULL);
28053  }
28054  sum = Cudd_Not(sum);
28055  Cudd_Ref(sum);
28056  Cudd_RecursiveDeref(dd, term0);
28057  Cudd_RecursiveDeref(dd, term1);
28058  /* r = sum + Id */
28059  r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
28060  r = Cudd_NotCond(r, r != NULL);
28061  if (r == NULL) {
28062  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
28063  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
28064  Cudd_RecursiveDeref(dd, Id);
28065  Cudd_RecursiveDerefZdd(dd, zdd_Id);
28066  Cudd_RecursiveDeref(dd, sum);
28067  return(NULL);
28068  }
28069  Cudd_Ref(r);
28070  Cudd_RecursiveDeref(dd, sum);
28071  Cudd_RecursiveDeref(dd, Id);
28072 
28073  if (zdd_Isub0 != zdd_zero) {
28074  z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id);
28075  if (z == NULL) {
28076  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
28077  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
28078  Cudd_RecursiveDerefZdd(dd, zdd_Id);
28079  Cudd_RecursiveDeref(dd, r);
28080  return(NULL);
28081  }
28082  }
28083  else {
28084  z = zdd_Id;
28085  }
28086  Cudd_Ref(z);
28087  if (zdd_Isub1 != zdd_zero) {
28088  y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z);
28089  if (y == NULL) {
28090  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
28091  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
28092  Cudd_RecursiveDerefZdd(dd, zdd_Id);
28093  Cudd_RecursiveDeref(dd, r);
28094  Cudd_RecursiveDerefZdd(dd, z);
28095  return(NULL);
28096  }
28097  }
28098  else
28099  y = z;
28100  Cudd_Ref(y);
28101 
28102  Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
28103  Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
28104  Cudd_RecursiveDerefZdd(dd, zdd_Id);
28105  Cudd_RecursiveDerefZdd(dd, z);
28106 
28107  cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
28108  cuddCacheInsert2(dd, cacheOp, L, U, y);
28109 
28110  Cudd_Deref(r);
28111  Cudd_Deref(y);
28112  *zdd_I = y;
28113  /*
28114  if (Cudd_Regular(r)->index != y->index / 2) {
28115  printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n");
28116  }
28117  */
28118  return(r);
28119 
28120 } /* end of cuddZddIsop */
28121 
28122 
28134 DdNode *
28136  DdManager * dd,
28137  DdNode * L,
28138  DdNode * U)
28139 {
28140  DdNode *one = DD_ONE(dd);
28141  DdNode *zero = Cudd_Not(one);
28142  int v, top_l, top_u;
28143  DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
28144  DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
28145  DdNode *Isub0, *Isub1, *Id;
28146  DdNode *x;
28147  DdNode *term0, *term1, *sum;
28148  DdNode *Lv, *Uv, *Lnv, *Unv;
28149  DdNode *r;
28150  int index;
28151 
28152  statLine(dd);
28153  if (L == zero)
28154  return(zero);
28155  if (U == one)
28156  return(one);
28157 
28158  /* Check cache */
28159  r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
28160  if (r)
28161  return(r);
28162 
28163  top_l = dd->perm[Cudd_Regular(L)->index];
28164  top_u = dd->perm[Cudd_Regular(U)->index];
28165  v = ddMin(top_l, top_u);
28166 
28167  /* Compute cofactors */
28168  if (top_l == v) {
28169  index = Cudd_Regular(L)->index;
28170  Lv = Cudd_T(L);
28171  Lnv = Cudd_E(L);
28172  if (Cudd_IsComplement(L)) {
28173  Lv = Cudd_Not(Lv);
28174  Lnv = Cudd_Not(Lnv);
28175  }
28176  }
28177  else {
28178  index = Cudd_Regular(U)->index;
28179  Lv = Lnv = L;
28180  }
28181 
28182  if (top_u == v) {
28183  Uv = Cudd_T(U);
28184  Unv = Cudd_E(U);
28185  if (Cudd_IsComplement(U)) {
28186  Uv = Cudd_Not(Uv);
28187  Unv = Cudd_Not(Unv);
28188  }
28189  }
28190  else {
28191  Uv = Unv = U;
28192  }
28193 
28194  Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
28195  if (Lsub0 == NULL)
28196  return(NULL);
28197  Cudd_Ref(Lsub0);
28198  Usub0 = Unv;
28199  Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
28200  if (Lsub1 == NULL) {
28201  Cudd_RecursiveDeref(dd, Lsub0);
28202  return(NULL);
28203  }
28204  Cudd_Ref(Lsub1);
28205  Usub1 = Uv;
28206 
28207  Isub0 = cuddBddIsop(dd, Lsub0, Usub0);
28208  if (Isub0 == NULL) {
28209  Cudd_RecursiveDeref(dd, Lsub0);
28210  Cudd_RecursiveDeref(dd, Lsub1);
28211  return(NULL);
28212  }
28213  Cudd_Ref(Isub0);
28214  Isub1 = cuddBddIsop(dd, Lsub1, Usub1);
28215  if (Isub1 == NULL) {
28216  Cudd_RecursiveDeref(dd, Lsub0);
28217  Cudd_RecursiveDeref(dd, Lsub1);
28218  Cudd_RecursiveDeref(dd, Isub0);
28219  return(NULL);
28220  }
28221  Cudd_Ref(Isub1);
28222  Cudd_RecursiveDeref(dd, Lsub0);
28223  Cudd_RecursiveDeref(dd, Lsub1);
28224 
28225  Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
28226  if (Lsuper0 == NULL) {
28227  Cudd_RecursiveDeref(dd, Isub0);
28228  Cudd_RecursiveDeref(dd, Isub1);
28229  return(NULL);
28230  }
28231  Cudd_Ref(Lsuper0);
28232  Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
28233  if (Lsuper1 == NULL) {
28234  Cudd_RecursiveDeref(dd, Isub0);
28235  Cudd_RecursiveDeref(dd, Isub1);
28236  Cudd_RecursiveDeref(dd, Lsuper0);
28237  return(NULL);
28238  }
28239  Cudd_Ref(Lsuper1);
28240  Usuper0 = Unv;
28241  Usuper1 = Uv;
28242 
28243  /* Ld = Lsuper0 + Lsuper1 */
28244  Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
28245  Ld = Cudd_NotCond(Ld, Ld != NULL);
28246  if (Ld == NULL) {
28247  Cudd_RecursiveDeref(dd, Isub0);
28248  Cudd_RecursiveDeref(dd, Isub1);
28249  Cudd_RecursiveDeref(dd, Lsuper0);
28250  Cudd_RecursiveDeref(dd, Lsuper1);
28251  return(NULL);
28252  }
28253  Cudd_Ref(Ld);
28254  Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
28255  if (Ud == NULL) {
28256  Cudd_RecursiveDeref(dd, Isub0);
28257  Cudd_RecursiveDeref(dd, Isub1);
28258  Cudd_RecursiveDeref(dd, Lsuper0);
28259  Cudd_RecursiveDeref(dd, Lsuper1);
28260  Cudd_RecursiveDeref(dd, Ld);
28261  return(NULL);
28262  }
28263  Cudd_Ref(Ud);
28264  Cudd_RecursiveDeref(dd, Lsuper0);
28265  Cudd_RecursiveDeref(dd, Lsuper1);
28266 
28267  Id = cuddBddIsop(dd, Ld, Ud);
28268  if (Id == NULL) {
28269  Cudd_RecursiveDeref(dd, Isub0);
28270  Cudd_RecursiveDeref(dd, Isub1);
28271  Cudd_RecursiveDeref(dd, Ld);
28272  Cudd_RecursiveDeref(dd, Ud);
28273  return(NULL);
28274  }
28275  Cudd_Ref(Id);
28276  Cudd_RecursiveDeref(dd, Ld);
28277  Cudd_RecursiveDeref(dd, Ud);
28278 
28279  x = cuddUniqueInter(dd, index, one, zero);
28280  if (x == NULL) {
28281  Cudd_RecursiveDeref(dd, Isub0);
28282  Cudd_RecursiveDeref(dd, Isub1);
28283  Cudd_RecursiveDeref(dd, Id);
28284  return(NULL);
28285  }
28286  Cudd_Ref(x);
28287  term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
28288  if (term0 == NULL) {
28289  Cudd_RecursiveDeref(dd, Isub0);
28290  Cudd_RecursiveDeref(dd, Isub1);
28291  Cudd_RecursiveDeref(dd, Id);
28292  Cudd_RecursiveDeref(dd, x);
28293  return(NULL);
28294  }
28295  Cudd_Ref(term0);
28296  Cudd_RecursiveDeref(dd, Isub0);
28297  term1 = cuddBddAndRecur(dd, x, Isub1);
28298  if (term1 == NULL) {
28299  Cudd_RecursiveDeref(dd, Isub1);
28300  Cudd_RecursiveDeref(dd, Id);
28301  Cudd_RecursiveDeref(dd, x);
28302  Cudd_RecursiveDeref(dd, term0);
28303  return(NULL);
28304  }
28305  Cudd_Ref(term1);
28306  Cudd_RecursiveDeref(dd, x);
28307  Cudd_RecursiveDeref(dd, Isub1);
28308  /* sum = term0 + term1 */
28309  sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
28310  sum = Cudd_NotCond(sum, sum != NULL);
28311  if (sum == NULL) {
28312  Cudd_RecursiveDeref(dd, Id);
28313  Cudd_RecursiveDeref(dd, term0);
28314  Cudd_RecursiveDeref(dd, term1);
28315  return(NULL);
28316  }
28317  Cudd_Ref(sum);
28318  Cudd_RecursiveDeref(dd, term0);
28319  Cudd_RecursiveDeref(dd, term1);
28320  /* r = sum + Id */
28321  r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
28322  r = Cudd_NotCond(r, r != NULL);
28323  if (r == NULL) {
28324  Cudd_RecursiveDeref(dd, Id);
28325  Cudd_RecursiveDeref(dd, sum);
28326  return(NULL);
28327  }
28328  Cudd_Ref(r);
28329  Cudd_RecursiveDeref(dd, sum);
28330  Cudd_RecursiveDeref(dd, Id);
28331 
28332  cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
28333 
28334  Cudd_Deref(r);
28335  return(r);
28336 
28337 } /* end of cuddBddIsop */
28338 
28339 
28359 DdNode *
28361  DdManager * dd,
28362  DdNode * node)
28363 {
28364  DdNode *neW;
28365  int v;
28366  DdNode *f1, *f0, *fd;
28367  DdNode *b1, *b0, *bd;
28368  DdNode *T, *E;
28369 
28370  statLine(dd);
28371  if (node == dd->one)
28372  return(dd->one);
28373  if (node == dd->zero)
28374  return(Cudd_Not(dd->one));
28375 
28376  /* Check cache */
28377  neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node);
28378  if (neW)
28379  return(neW);
28380 
28381  v = Cudd_Regular(node)->index; /* either yi or zi */
28382  if (cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd)) return(NULL);
28383  Cudd_Ref(f1);
28384  Cudd_Ref(f0);
28385  Cudd_Ref(fd);
28386 
28387  b1 = cuddMakeBddFromZddCover(dd, f1);
28388  if (!b1) {
28389  Cudd_RecursiveDerefZdd(dd, f1);
28390  Cudd_RecursiveDerefZdd(dd, f0);
28391  Cudd_RecursiveDerefZdd(dd, fd);
28392  return(NULL);
28393  }
28394  Cudd_Ref(b1);
28395  b0 = cuddMakeBddFromZddCover(dd, f0);
28396  if (!b0) {
28397  Cudd_RecursiveDerefZdd(dd, f1);
28398  Cudd_RecursiveDerefZdd(dd, f0);
28399  Cudd_RecursiveDerefZdd(dd, fd);
28400  Cudd_RecursiveDeref(dd, b1);
28401  return(NULL);
28402  }
28403  Cudd_Ref(b0);
28404  Cudd_RecursiveDerefZdd(dd, f1);
28405  Cudd_RecursiveDerefZdd(dd, f0);
28406  if (fd != dd->zero) {
28407  bd = cuddMakeBddFromZddCover(dd, fd);
28408  if (!bd) {
28409  Cudd_RecursiveDerefZdd(dd, fd);
28410  Cudd_RecursiveDeref(dd, b1);
28411  Cudd_RecursiveDeref(dd, b0);
28412  return(NULL);
28413  }
28414  Cudd_Ref(bd);
28415  Cudd_RecursiveDerefZdd(dd, fd);
28416 
28417  T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd));
28418  if (!T) {
28419  Cudd_RecursiveDeref(dd, b1);
28420  Cudd_RecursiveDeref(dd, b0);
28421  Cudd_RecursiveDeref(dd, bd);
28422  return(NULL);
28423  }
28424  T = Cudd_NotCond(T, T != NULL);
28425  Cudd_Ref(T);
28426  Cudd_RecursiveDeref(dd, b1);
28427  E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd));
28428  if (!E) {
28429  Cudd_RecursiveDeref(dd, b0);
28430  Cudd_RecursiveDeref(dd, bd);
28431  Cudd_RecursiveDeref(dd, T);
28432  return(NULL);
28433  }
28434  E = Cudd_NotCond(E, E != NULL);
28435  Cudd_Ref(E);
28436  Cudd_RecursiveDeref(dd, b0);
28437  Cudd_RecursiveDeref(dd, bd);
28438  }
28439  else {
28440  Cudd_RecursiveDerefZdd(dd, fd);
28441  T = b1;
28442  E = b0;
28443  }
28444 
28445  if (Cudd_IsComplement(T)) {
28446  neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E));
28447  if (!neW) {
28448  Cudd_RecursiveDeref(dd, T);
28449  Cudd_RecursiveDeref(dd, E);
28450  return(NULL);
28451  }
28452  neW = Cudd_Not(neW);
28453  }
28454  else {
28455  neW = cuddUniqueInterIVO(dd, v / 2, T, E);
28456  if (!neW) {
28457  Cudd_RecursiveDeref(dd, T);
28458  Cudd_RecursiveDeref(dd, E);
28459  return(NULL);
28460  }
28461  }
28462  Cudd_Ref(neW);
28463  Cudd_RecursiveDeref(dd, T);
28464  Cudd_RecursiveDeref(dd, E);
28465 
28466  cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW);
28467  Cudd_Deref(neW);
28468  return(neW);
28469 
28470 } /* end of cuddMakeBddFromZddCover */
28471 
28472 
28473 /*---------------------------------------------------------------------------*/
28474 /* Definition of static functions */
28475 /*---------------------------------------------------------------------------*/
28538 /*---------------------------------------------------------------------------*/
28539 /* Constant declarations */
28540 /*---------------------------------------------------------------------------*/
28541 
28542 #define CUDD_SWAP_MOVE 0
28543 #define CUDD_LINEAR_TRANSFORM_MOVE 1
28544 #define CUDD_INVERSE_TRANSFORM_MOVE 2
28545 
28546 /*---------------------------------------------------------------------------*/
28547 /* Stucture declarations */
28548 /*---------------------------------------------------------------------------*/
28549 
28550 
28551 /*---------------------------------------------------------------------------*/
28552 /* Type declarations */
28553 /*---------------------------------------------------------------------------*/
28554 
28555 
28556 /*---------------------------------------------------------------------------*/
28557 /* Variable declarations */
28558 /*---------------------------------------------------------------------------*/
28559 
28560 //#ifndef lint
28561 //static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.16 2012/02/05 01:07:19 fabio Exp $";
28562 //#endif
28563 
28564 extern int *zdd_entry;
28567 static DdNode *empty;
28568 
28569 
28570 /*---------------------------------------------------------------------------*/
28571 /* Macro declarations */
28572 /*---------------------------------------------------------------------------*/
28573 
28574 
28577 /*---------------------------------------------------------------------------*/
28578 /* Static function prototypes */
28579 /*---------------------------------------------------------------------------*/
28580 
28581 static int cuddZddLinearInPlace (DdManager * table, int x, int y);
28582 static int cuddZddLinearAux (DdManager *table, int x, int xLow, int xHigh);
28583 static Move * cuddZddLinearUp (DdManager *table, int y, int xLow, Move *prevMoves);
28584 static Move * cuddZddLinearDown (DdManager *table, int x, int xHigh, Move *prevMoves);
28585 static int cuddZddLinearBackward (DdManager *table, int size, Move *moves);
28586 static Move* cuddZddUndoMoves (DdManager *table, Move *moves);
28587 
28591 /*---------------------------------------------------------------------------*/
28592 /* Definition of exported functions */
28593 /*---------------------------------------------------------------------------*/
28594 
28595 
28596 /*---------------------------------------------------------------------------*/
28597 /* Definition of internal functions */
28598 /*---------------------------------------------------------------------------*/
28599 
28600 
28601 
28602 
28624 int
28626  DdManager * table,
28627  int lower,
28628  int upper)
28629 {
28630  int i;
28631  int *var;
28632  int size;
28633  int x;
28634  int result;
28635 #ifdef DD_STATS
28636  int previousSize;
28637 #endif
28638 
28639  size = table->sizeZ;
28640  empty = table->zero;
28641 
28642  /* Find order in which to sift variables. */
28643  var = NULL;
28644  zdd_entry = ALLOC(int, size);
28645  if (zdd_entry == NULL) {
28646  table->errorCode = CUDD_MEMORY_OUT;
28647  goto cuddZddSiftingOutOfMem;
28648  }
28649  var = ALLOC(int, size);
28650  if (var == NULL) {
28651  table->errorCode = CUDD_MEMORY_OUT;
28652  goto cuddZddSiftingOutOfMem;
28653  }
28654 
28655  for (i = 0; i < size; i++) {
28656  x = table->permZ[i];
28657  zdd_entry[i] = table->subtableZ[x].keys;
28658  var[i] = i;
28659  }
28660 
28661  qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
28662 
28663  /* Now sift. */
28664  for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
28665  if (zddTotalNumberSwapping >= table->siftMaxSwap)
28666  break;
28667  if (util_cpu_time() - table->startTime > table->timeLimit) {
28668  table->autoDynZ = 0; /* prevent further reordering */
28669  break;
28670  }
28671  x = table->permZ[var[i]];
28672  if (x < lower || x > upper) continue;
28673 #ifdef DD_STATS
28674  previousSize = table->keysZ;
28675 #endif
28676  result = cuddZddLinearAux(table, x, lower, upper);
28677  if (!result)
28678  goto cuddZddSiftingOutOfMem;
28679 #ifdef DD_STATS
28680  if (table->keysZ < (unsigned) previousSize) {
28681  (void) fprintf(table->out,"-");
28682  } else if (table->keysZ > (unsigned) previousSize) {
28683  (void) fprintf(table->out,"+"); /* should never happen */
28684  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
28685  } else {
28686  (void) fprintf(table->out,"=");
28687  }
28688  fflush(table->out);
28689 #endif
28690  }
28691 
28692  FREE(var);
28693  FREE(zdd_entry);
28694 
28695  return(1);
28696 
28697  cuddZddSiftingOutOfMem:
28698 
28699  if (zdd_entry != NULL) FREE(zdd_entry);
28700  if (var != NULL) FREE(var);
28701 
28702  return(0);
28703 
28704 } /* end of cuddZddLinearSifting */
28705 
28706 
28707 /*---------------------------------------------------------------------------*/
28708 /* Definition of static functions */
28709 /*---------------------------------------------------------------------------*/
28710 
28711 
28727 static int
28729  DdManager * table,
28730  int x,
28731  int y)
28732 {
28733  DdNodePtr *xlist, *ylist;
28734  int xindex, yindex;
28735  int xslots, yslots;
28736  int xshift, yshift;
28737  int oldxkeys, oldykeys;
28738  int newxkeys, newykeys;
28739  int i;
28740  int posn;
28741  DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00;
28742  DdNode *newf1, *newf0, *g, *next, *previous;
28743  DdNode *special;
28744 
28745 #ifdef DD_DEBUG
28746  assert(x < y);
28747  assert(cuddZddNextHigh(table,x) == y);
28748  assert(table->subtableZ[x].keys != 0);
28749  assert(table->subtableZ[y].keys != 0);
28750  assert(table->subtableZ[x].dead == 0);
28751  assert(table->subtableZ[y].dead == 0);
28752 #endif
28753 
28755 
28756  /* Get parameters of x subtable. */
28757  xindex = table->invpermZ[x];
28758  xlist = table->subtableZ[x].nodelist;
28759  oldxkeys = table->subtableZ[x].keys;
28760  xslots = table->subtableZ[x].slots;
28761  xshift = table->subtableZ[x].shift;
28762  newxkeys = 0;
28763 
28764  /* Get parameters of y subtable. */
28765  yindex = table->invpermZ[y];
28766  ylist = table->subtableZ[y].nodelist;
28767  oldykeys = table->subtableZ[y].keys;
28768  yslots = table->subtableZ[y].slots;
28769  yshift = table->subtableZ[y].shift;
28770  newykeys = oldykeys;
28771 
28772  /* The nodes in the x layer are put in two chains. The chain
28773  ** pointed by g holds the normal nodes. When re-expressed they stay
28774  ** in the x list. The chain pointed by special holds the elements
28775  ** that will move to the y list.
28776  */
28777  g = special = NULL;
28778  for (i = 0; i < xslots; i++) {
28779  f = xlist[i];
28780  if (f == NULL) continue;
28781  xlist[i] = NULL;
28782  while (f != NULL) {
28783  next = f->next;
28784  f1 = cuddT(f);
28785  /* if (f1->index == yindex) */ cuddSatDec(f1->ref);
28786  f0 = cuddE(f);
28787  /* if (f0->index == yindex) */ cuddSatDec(f0->ref);
28788  if ((int) f1->index == yindex && cuddE(f1) == empty &&
28789  (int) f0->index != yindex) {
28790  f->next = special;
28791  special = f;
28792  } else {
28793  f->next = g;
28794  g = f;
28795  }
28796  f = next;
28797  } /* while there are elements in the collision chain */
28798  } /* for each slot of the x subtable */
28799 
28800  /* Mark y nodes with pointers from above x. We mark them by
28801  ** changing their index to x.
28802  */
28803  for (i = 0; i < yslots; i++) {
28804  f = ylist[i];
28805  while (f != NULL) {
28806  if (f->ref != 0) {
28807  f->index = xindex;
28808  }
28809  f = f->next;
28810  } /* while there are elements in the collision chain */
28811  } /* for each slot of the y subtable */
28812 
28813  /* Move special nodes to the y list. */
28814  f = special;
28815  while (f != NULL) {
28816  next = f->next;
28817  f1 = cuddT(f);
28818  f11 = cuddT(f1);
28819  cuddT(f) = f11;
28820  cuddSatInc(f11->ref);
28821  f0 = cuddE(f);
28822  cuddSatInc(f0->ref);
28823  f->index = yindex;
28824  /* Insert at the beginning of the list so that it will be
28825  ** found first if there is a duplicate. The duplicate will
28826  ** eventually be moved or garbage collected. No node
28827  ** re-expression will add a pointer to it.
28828  */
28829  posn = ddHash(f11, f0, yshift);
28830  f->next = ylist[posn];
28831  ylist[posn] = f;
28832  newykeys++;
28833  f = next;
28834  }
28835 
28836  /* Take care of the remaining x nodes that must be re-expressed.
28837  ** They form a linked list pointed by g.
28838  */
28839  f = g;
28840  while (f != NULL) {
28841 #ifdef DD_COUNT
28842  table->swapSteps++;
28843 #endif
28844  next = f->next;
28845  /* Find f1, f0, f11, f10, f01, f00. */
28846  f1 = cuddT(f);
28847  if ((int) f1->index == yindex || (int) f1->index == xindex) {
28848  f11 = cuddT(f1); f10 = cuddE(f1);
28849  } else {
28850  f11 = empty; f10 = f1;
28851  }
28852  f0 = cuddE(f);
28853  if ((int) f0->index == yindex || (int) f0->index == xindex) {
28854  f01 = cuddT(f0); f00 = cuddE(f0);
28855  } else {
28856  f01 = empty; f00 = f0;
28857  }
28858  /* Create the new T child. */
28859  if (f01 == empty) {
28860  newf1 = f10;
28861  cuddSatInc(newf1->ref);
28862  } else {
28863  /* Check ylist for triple (yindex, f01, f10). */
28864  posn = ddHash(f01, f10, yshift);
28865  /* For each element newf1 in collision list ylist[posn]. */
28866  newf1 = ylist[posn];
28867  /* Search the collision chain skipping the marked nodes. */
28868  while (newf1 != NULL) {
28869  if (cuddT(newf1) == f01 && cuddE(newf1) == f10 &&
28870  (int) newf1->index == yindex) {
28871  cuddSatInc(newf1->ref);
28872  break; /* match */
28873  }
28874  newf1 = newf1->next;
28875  } /* while newf1 */
28876  if (newf1 == NULL) { /* no match */
28877  newf1 = cuddDynamicAllocNode(table);
28878  if (newf1 == NULL)
28879  goto zddSwapOutOfMem;
28880  newf1->index = yindex; newf1->ref = 1;
28881  cuddT(newf1) = f01;
28882  cuddE(newf1) = f10;
28883  /* Insert newf1 in the collision list ylist[pos];
28884  ** increase the ref counts of f01 and f10
28885  */
28886  newykeys++;
28887  newf1->next = ylist[posn];
28888  ylist[posn] = newf1;
28889  cuddSatInc(f01->ref);
28890  cuddSatInc(f10->ref);
28891  }
28892  }
28893  cuddT(f) = newf1;
28894 
28895  /* Do the same for f0. */
28896  /* Create the new E child. */
28897  if (f11 == empty) {
28898  newf0 = f00;
28899  cuddSatInc(newf0->ref);
28900  } else {
28901  /* Check ylist for triple (yindex, f11, f00). */
28902  posn = ddHash(f11, f00, yshift);
28903  /* For each element newf0 in collision list ylist[posn]. */
28904  newf0 = ylist[posn];
28905  while (newf0 != NULL) {
28906  if (cuddT(newf0) == f11 && cuddE(newf0) == f00 &&
28907  (int) newf0->index == yindex) {
28908  cuddSatInc(newf0->ref);
28909  break; /* match */
28910  }
28911  newf0 = newf0->next;
28912  } /* while newf0 */
28913  if (newf0 == NULL) { /* no match */
28914  newf0 = cuddDynamicAllocNode(table);
28915  if (newf0 == NULL)
28916  goto zddSwapOutOfMem;
28917  newf0->index = yindex; newf0->ref = 1;
28918  cuddT(newf0) = f11; cuddE(newf0) = f00;
28919  /* Insert newf0 in the collision list ylist[posn];
28920  ** increase the ref counts of f11 and f00.
28921  */
28922  newykeys++;
28923  newf0->next = ylist[posn];
28924  ylist[posn] = newf0;
28925  cuddSatInc(f11->ref);
28926  cuddSatInc(f00->ref);
28927  }
28928  }
28929  cuddE(f) = newf0;
28930 
28931  /* Re-insert the modified f in xlist.
28932  ** The modified f does not already exists in xlist.
28933  ** (Because of the uniqueness of the cofactors.)
28934  */
28935  posn = ddHash(newf1, newf0, xshift);
28936  newxkeys++;
28937  f->next = xlist[posn];
28938  xlist[posn] = f;
28939  f = next;
28940  } /* while f != NULL */
28941 
28942  /* GC the y layer and move the marked nodes to the x list. */
28943 
28944  /* For each node f in ylist. */
28945  for (i = 0; i < yslots; i++) {
28946  previous = NULL;
28947  f = ylist[i];
28948  while (f != NULL) {
28949  next = f->next;
28950  if (f->ref == 0) {
28951  cuddSatDec(cuddT(f)->ref);
28952  cuddSatDec(cuddE(f)->ref);
28953  cuddDeallocNode(table, f);
28954  newykeys--;
28955  if (previous == NULL)
28956  ylist[i] = next;
28957  else
28958  previous->next = next;
28959  } else if ((int) f->index == xindex) { /* move marked node */
28960  if (previous == NULL)
28961  ylist[i] = next;
28962  else
28963  previous->next = next;
28964  f1 = cuddT(f);
28965  cuddSatDec(f1->ref);
28966  /* Check ylist for triple (yindex, f1, empty). */
28967  posn = ddHash(f1, empty, yshift);
28968  /* For each element newf1 in collision list ylist[posn]. */
28969  newf1 = ylist[posn];
28970  while (newf1 != NULL) {
28971  if (cuddT(newf1) == f1 && cuddE(newf1) == empty &&
28972  (int) newf1->index == yindex) {
28973  cuddSatInc(newf1->ref);
28974  break; /* match */
28975  }
28976  newf1 = newf1->next;
28977  } /* while newf1 */
28978  if (newf1 == NULL) { /* no match */
28979  newf1 = cuddDynamicAllocNode(table);
28980  if (newf1 == NULL)
28981  goto zddSwapOutOfMem;
28982  newf1->index = yindex; newf1->ref = 1;
28983  cuddT(newf1) = f1; cuddE(newf1) = empty;
28984  /* Insert newf1 in the collision list ylist[posn];
28985  ** increase the ref counts of f1 and empty.
28986  */
28987  newykeys++;
28988  newf1->next = ylist[posn];
28989  ylist[posn] = newf1;
28990  if (posn == i && previous == NULL)
28991  previous = newf1;
28992  cuddSatInc(f1->ref);
28993  cuddSatInc(empty->ref);
28994  }
28995  cuddT(f) = newf1;
28996  f0 = cuddE(f);
28997  /* Insert f in x list. */
28998  posn = ddHash(newf1, f0, xshift);
28999  newxkeys++;
29000  newykeys--;
29001  f->next = xlist[posn];
29002  xlist[posn] = f;
29003  } else {
29004  previous = f;
29005  }
29006  f = next;
29007  } /* while f */
29008  } /* for i */
29009 
29010  /* Set the appropriate fields in table. */
29011  table->subtableZ[x].keys = newxkeys;
29012  table->subtableZ[y].keys = newykeys;
29013 
29014  table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
29015 
29016  /* Update univ section; univ[x] remains the same. */
29017  table->univ[y] = cuddT(table->univ[x]);
29018 
29019 #if 0
29020  (void) fprintf(table->out,"x = %d y = %d\n", x, y);
29021  (void) Cudd_DebugCheck(table);
29022  (void) Cudd_CheckKeys(table);
29023 #endif
29024 
29025  return (table->keysZ);
29026 
29027  zddSwapOutOfMem:
29028  (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
29029 
29030  return (0);
29031 
29032 } /* end of cuddZddLinearInPlace */
29033 
29034 
29049 static int
29051  DdManager * table,
29052  int x,
29053  int xLow,
29054  int xHigh)
29055 {
29056  Move *move;
29057  Move *moveUp; /* list of up move */
29058  Move *moveDown; /* list of down move */
29059 
29060  int initial_size;
29061  int result;
29062 
29063  initial_size = table->keysZ;
29064 
29065 #ifdef DD_DEBUG
29066  assert(table->subtableZ[x].keys > 0);
29067 #endif
29068 
29069  moveDown = NULL;
29070  moveUp = NULL;
29071 
29072  if (x == xLow) {
29073  moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
29074  /* At this point x --> xHigh. */
29075  if (moveDown == (Move *) CUDD_OUT_OF_MEM)
29076  goto cuddZddLinearAuxOutOfMem;
29077  /* Move backward and stop at best position. */
29078  result = cuddZddLinearBackward(table, initial_size, moveDown);
29079  if (!result)
29080  goto cuddZddLinearAuxOutOfMem;
29081 
29082  } else if (x == xHigh) {
29083  moveUp = cuddZddLinearUp(table, x, xLow, NULL);
29084  /* At this point x --> xLow. */
29085  if (moveUp == (Move *) CUDD_OUT_OF_MEM)
29086  goto cuddZddLinearAuxOutOfMem;
29087  /* Move backward and stop at best position. */
29088  result = cuddZddLinearBackward(table, initial_size, moveUp);
29089  if (!result)
29090  goto cuddZddLinearAuxOutOfMem;
29091 
29092  } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
29093  moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
29094  /* At this point x --> xHigh. */
29095  if (moveDown == (Move *) CUDD_OUT_OF_MEM)
29096  goto cuddZddLinearAuxOutOfMem;
29097  moveUp = cuddZddUndoMoves(table,moveDown);
29098 #ifdef DD_DEBUG
29099  assert(moveUp == NULL || moveUp->x == x);
29100 #endif
29101  moveUp = cuddZddLinearUp(table, x, xLow, moveUp);
29102  if (moveUp == (Move *) CUDD_OUT_OF_MEM)
29103  goto cuddZddLinearAuxOutOfMem;
29104  /* Move backward and stop at best position. */
29105  result = cuddZddLinearBackward(table, initial_size, moveUp);
29106  if (!result)
29107  goto cuddZddLinearAuxOutOfMem;
29108 
29109  } else {
29110  moveUp = cuddZddLinearUp(table, x, xLow, NULL);
29111  /* At this point x --> xHigh. */
29112  if (moveUp == (Move *) CUDD_OUT_OF_MEM)
29113  goto cuddZddLinearAuxOutOfMem;
29114  /* Then move up. */
29115  moveDown = cuddZddUndoMoves(table,moveUp);
29116 #ifdef DD_DEBUG
29117  assert(moveDown == NULL || moveDown->y == x);
29118 #endif
29119  moveDown = cuddZddLinearDown(table, x, xHigh, moveDown);
29120  if (moveDown == (Move *) CUDD_OUT_OF_MEM)
29121  goto cuddZddLinearAuxOutOfMem;
29122  /* Move backward and stop at best position. */
29123  result = cuddZddLinearBackward(table, initial_size, moveDown);
29124  if (!result)
29125  goto cuddZddLinearAuxOutOfMem;
29126  }
29127 
29128  while (moveDown != NULL) {
29129  move = moveDown->next;
29130  cuddDeallocMove(table, moveDown);
29131  moveDown = move;
29132  }
29133  while (moveUp != NULL) {
29134  move = moveUp->next;
29135  cuddDeallocMove(table, moveUp);
29136  moveUp = move;
29137  }
29138 
29139  return(1);
29140 
29141  cuddZddLinearAuxOutOfMem:
29142  if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
29143  while (moveDown != NULL) {
29144  move = moveDown->next;
29145  cuddDeallocMove(table, moveDown);
29146  moveDown = move;
29147  }
29148  }
29149  if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
29150  while (moveUp != NULL) {
29151  move = moveUp->next;
29152  cuddDeallocMove(table, moveUp);
29153  moveUp = move;
29154  }
29155  }
29156 
29157  return(0);
29158 
29159 } /* end of cuddZddLinearAux */
29160 
29161 
29176 static Move *
29178  DdManager * table,
29179  int y,
29180  int xLow,
29181  Move * prevMoves)
29182 {
29183  Move *moves;
29184  Move *move;
29185  int x;
29186  int size, newsize;
29187  int limitSize;
29188 
29189  moves = prevMoves;
29190  limitSize = table->keysZ;
29191 
29192  x = cuddZddNextLow(table, y);
29193  while (x >= xLow) {
29194  size = cuddZddSwapInPlace(table, x, y);
29195  if (size == 0)
29196  goto cuddZddLinearUpOutOfMem;
29197  newsize = cuddZddLinearInPlace(table, x, y);
29198  if (newsize == 0)
29199  goto cuddZddLinearUpOutOfMem;
29200  move = (Move *) cuddDynamicAllocNode(table);
29201  if (move == NULL)
29202  goto cuddZddLinearUpOutOfMem;
29203  move->x = x;
29204  move->y = y;
29205  move->next = moves;
29206  moves = move;
29207  move->flags = CUDD_SWAP_MOVE;
29208  if (newsize > size) {
29209  /* Undo transformation. The transformation we apply is
29210  ** its own inverse. Hence, we just apply the transformation
29211  ** again.
29212  */
29213  newsize = cuddZddLinearInPlace(table,x,y);
29214  if (newsize == 0) goto cuddZddLinearUpOutOfMem;
29215 #ifdef DD_DEBUG
29216  if (newsize != size) {
29217  (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
29218  }
29219 #endif
29220  } else {
29221  size = newsize;
29223  }
29224  move->size = size;
29225 
29226  if ((double)size > (double)limitSize * table->maxGrowth)
29227  break;
29228  if (size < limitSize)
29229  limitSize = size;
29230 
29231  y = x;
29232  x = cuddZddNextLow(table, y);
29233  }
29234  return(moves);
29235 
29236  cuddZddLinearUpOutOfMem:
29237  while (moves != NULL) {
29238  move = moves->next;
29239  cuddDeallocMove(table, moves);
29240  moves = move;
29241  }
29242  return((Move *) CUDD_OUT_OF_MEM);
29243 
29244 } /* end of cuddZddLinearUp */
29245 
29246 
29261 static Move *
29263  DdManager * table,
29264  int x,
29265  int xHigh,
29266  Move * prevMoves)
29267 {
29268  Move *moves;
29269  Move *move;
29270  int y;
29271  int size, newsize;
29272  int limitSize;
29273 
29274  moves = prevMoves;
29275  limitSize = table->keysZ;
29276 
29277  y = cuddZddNextHigh(table, x);
29278  while (y <= xHigh) {
29279  size = cuddZddSwapInPlace(table, x, y);
29280  if (size == 0)
29281  goto cuddZddLinearDownOutOfMem;
29282  newsize = cuddZddLinearInPlace(table, x, y);
29283  if (newsize == 0)
29284  goto cuddZddLinearDownOutOfMem;
29285  move = (Move *) cuddDynamicAllocNode(table);
29286  if (move == NULL)
29287  goto cuddZddLinearDownOutOfMem;
29288  move->x = x;
29289  move->y = y;
29290  move->next = moves;
29291  moves = move;
29292  move->flags = CUDD_SWAP_MOVE;
29293  if (newsize > size) {
29294  /* Undo transformation. The transformation we apply is
29295  ** its own inverse. Hence, we just apply the transformation
29296  ** again.
29297  */
29298  newsize = cuddZddLinearInPlace(table,x,y);
29299  if (newsize == 0) goto cuddZddLinearDownOutOfMem;
29300  if (newsize != size) {
29301  (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
29302  }
29303  } else {
29304  size = newsize;
29306  }
29307  move->size = size;
29308 
29309  if ((double)size > (double)limitSize * table->maxGrowth)
29310  break;
29311  if (size < limitSize)
29312  limitSize = size;
29313 
29314  x = y;
29315  y = cuddZddNextHigh(table, x);
29316  }
29317  return(moves);
29318 
29319  cuddZddLinearDownOutOfMem:
29320  while (moves != NULL) {
29321  move = moves->next;
29322  cuddDeallocMove(table, moves);
29323  moves = move;
29324  }
29325  return((Move *) CUDD_OUT_OF_MEM);
29326 
29327 } /* end of cuddZddLinearDown */
29328 
29329 
29345 static int
29347  DdManager * table,
29348  int size,
29349  Move * moves)
29350 {
29351  Move *move;
29352  int res;
29353 
29354  /* Find the minimum size among moves. */
29355  for (move = moves; move != NULL; move = move->next) {
29356  if (move->size < size) {
29357  size = move->size;
29358  }
29359  }
29360 
29361  for (move = moves; move != NULL; move = move->next) {
29362  if (move->size == size) return(1);
29363  if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
29364  res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
29365  if (!res) return(0);
29366  }
29367  res = cuddZddSwapInPlace(table, move->x, move->y);
29368  if (!res)
29369  return(0);
29370  if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
29371  res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
29372  if (!res) return(0);
29373  }
29374  }
29375 
29376  return(1);
29377 
29378 } /* end of cuddZddLinearBackward */
29379 
29380 
29393 static Move*
29395  DdManager * table,
29396  Move * moves)
29397 {
29398  Move *invmoves = NULL;
29399  Move *move;
29400  Move *invmove;
29401  int size;
29402 
29403  for (move = moves; move != NULL; move = move->next) {
29404  invmove = (Move *) cuddDynamicAllocNode(table);
29405  if (invmove == NULL) goto cuddZddUndoMovesOutOfMem;
29406  invmove->x = move->x;
29407  invmove->y = move->y;
29408  invmove->next = invmoves;
29409  invmoves = invmove;
29410  if (move->flags == CUDD_SWAP_MOVE) {
29411  invmove->flags = CUDD_SWAP_MOVE;
29412  size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
29413  if (!size) goto cuddZddUndoMovesOutOfMem;
29414  } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
29416  size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
29417  if (!size) goto cuddZddUndoMovesOutOfMem;
29418  size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
29419  if (!size) goto cuddZddUndoMovesOutOfMem;
29420  } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
29421 #ifdef DD_DEBUG
29422  (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
29423 #endif
29424  invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
29425  size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
29426  if (!size) goto cuddZddUndoMovesOutOfMem;
29427  size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
29428  if (!size) goto cuddZddUndoMovesOutOfMem;
29429  }
29430  invmove->size = size;
29431  }
29432 
29433  return(invmoves);
29434 
29435  cuddZddUndoMovesOutOfMem:
29436  while (invmoves != NULL) {
29437  move = invmoves->next;
29438  cuddDeallocMove(table, invmoves);
29439  invmoves = move;
29440  }
29441  return((Move *) CUDD_OUT_OF_MEM);
29442 
29443 } /* end of cuddZddUndoMoves */
29444 
29521 /*---------------------------------------------------------------------------*/
29522 /* Constant declarations */
29523 /*---------------------------------------------------------------------------*/
29524 
29525 #define DD_MAX_SUBTABLE_SPARSITY 8
29526 
29527 /*---------------------------------------------------------------------------*/
29528 /* Stucture declarations */
29529 /*---------------------------------------------------------------------------*/
29530 
29531 
29532 /*---------------------------------------------------------------------------*/
29533 /* Type declarations */
29534 /*---------------------------------------------------------------------------*/
29535 
29536 
29537 /*---------------------------------------------------------------------------*/
29538 /* Variable declarations */
29539 /*---------------------------------------------------------------------------*/
29540 
29541 //#ifndef lint
29542 //static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.49 2012/02/05 01:07:19 fabio Exp $";
29543 //#endif
29544 
29546 
29548 
29549 static DdNode *empty;
29550 
29551 
29552 /*---------------------------------------------------------------------------*/
29553 /* Macro declarations */
29554 /*---------------------------------------------------------------------------*/
29555 
29556 
29559 /*---------------------------------------------------------------------------*/
29560 /* Static function prototypes */
29561 /*---------------------------------------------------------------------------*/
29562 
29563 static Move * zddSwapAny (DdManager *table, int x, int y);
29564 static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high);
29565 static Move * cuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size);
29566 static Move * cuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size);
29567 static int cuddZddSiftingBackward (DdManager *table, Move *moves, int size);
29568 static void zddReorderPreprocess (DdManager *table);
29569 static int zddReorderPostprocess (DdManager *table);
29570 static int zddShuffle (DdManager *table, int *permutation);
29571 static int zddSiftUp (DdManager *table, int x, int xLow);
29572 static void zddFixTree (DdManager *table, MtrNode *treenode);
29573 
29577 /*---------------------------------------------------------------------------*/
29578 /* Definition of exported functions */
29579 /*---------------------------------------------------------------------------*/
29580 
29581 
29607 int
29609  DdManager * table /* DD manager */,
29610  Cudd_ReorderingType heuristic /* method used for reordering */,
29611  int minsize /* bound below which no reordering occurs */)
29612 {
29613  DdHook *hook;
29614  int result;
29615  unsigned int nextDyn;
29616 #ifdef DD_STATS
29617  unsigned int initialSize;
29618  unsigned int finalSize;
29619 #endif
29620  unsigned long localTime;
29621 
29622  /* Don't reorder if there are too many dead nodes. */
29623  if (table->keysZ - table->deadZ < (unsigned) minsize)
29624  return(1);
29625 
29626  if (heuristic == CUDD_REORDER_SAME) {
29627  heuristic = table->autoMethodZ;
29628  }
29629  if (heuristic == CUDD_REORDER_NONE) {
29630  return(1);
29631  }
29632 
29633  /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore
29634  ** we count it.
29635  */
29636  table->reorderings++;
29637  empty = table->zero;
29638 
29639  localTime = util_cpu_time();
29640 
29641  /* Run the hook functions. */
29642  hook = table->preReorderingHook;
29643  while (hook != NULL) {
29644  int res = (hook->f)(table, "ZDD", (void *)heuristic);
29645  if (res == 0) return(0);
29646  hook = hook->next;
29647  }
29648 
29649  /* Clear the cache and collect garbage. */
29650  zddReorderPreprocess(table);
29652 
29653 #ifdef DD_STATS
29654  initialSize = table->keysZ;
29655 
29656  switch(heuristic) {
29657  case CUDD_REORDER_RANDOM:
29659  (void) fprintf(table->out,"#:I_RANDOM ");
29660  break;
29661  case CUDD_REORDER_SIFT:
29665  (void) fprintf(table->out,"#:I_SIFTING ");
29666  break;
29667  case CUDD_REORDER_LINEAR:
29669  (void) fprintf(table->out,"#:I_LINSIFT ");
29670  break;
29671  default:
29672  (void) fprintf(table->err,"Unsupported ZDD reordering method\n");
29673  return(0);
29674  }
29675  (void) fprintf(table->out,"%8d: initial size",initialSize);
29676 #endif
29677 
29678  result = cuddZddTreeSifting(table,heuristic);
29679 
29680 #ifdef DD_STATS
29681  (void) fprintf(table->out,"\n");
29682  finalSize = table->keysZ;
29683  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
29684  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
29685  ((double)(util_cpu_time() - localTime)/1000.0));
29686  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
29688 #endif
29689 
29690  if (result == 0)
29691  return(0);
29692 
29693  if (!zddReorderPostprocess(table))
29694  return(0);
29695 
29696  if (table->realignZ) {
29697  if (!cuddBddAlignToZdd(table))
29698  return(0);
29699  }
29700 
29701  nextDyn = table->keysZ * DD_DYN_RATIO;
29702  if (table->reorderings < 20 || nextDyn > table->nextDyn)
29703  table->nextDyn = nextDyn;
29704  else
29705  table->nextDyn += 20;
29706 
29707  table->reordered = 1;
29708 
29709  /* Run hook functions. */
29710  hook = table->postReorderingHook;
29711  while (hook != NULL) {
29712  int res = (hook->f)(table, "ZDD", (void *)localTime);
29713  if (res == 0) return(0);
29714  hook = hook->next;
29715  }
29716  /* Update cumulative reordering time. */
29717  table->reordTime += util_cpu_time() - localTime;
29718 
29719  return(result);
29720 
29721 } /* end of Cudd_zddReduceHeap */
29722 
29723 
29724 /*---------------------------------------------------------------------------*/
29725 /* Definition of internal functions */
29726 /*---------------------------------------------------------------------------*/
29727 
29728 
29752 int
29754  DdManager * table /* DD manager */)
29755 {
29756  int *invpermZ; /* permutation array */
29757  int M; /* ratio of ZDD variables to BDD variables */
29758  int i,j; /* loop indices */
29759  int result; /* return value */
29760 
29761  /* We assume that a ratio of 0 is OK. */
29762  if (table->sizeZ == 0)
29763  return(1);
29764 
29765  empty = table->zero;
29766  M = table->sizeZ / table->size;
29767  /* Check whether the number of ZDD variables is a multiple of the
29768  ** number of BDD variables.
29769  */
29770  if (M * table->size != table->sizeZ)
29771  return(0);
29772  /* Create and initialize the inverse permutation array. */
29773  invpermZ = ALLOC(int,table->sizeZ);
29774  if (invpermZ == NULL) {
29775  table->errorCode = CUDD_MEMORY_OUT;
29776  return(0);
29777  }
29778  for (i = 0; i < table->size; i++) {
29779  int index = table->invperm[i];
29780  int indexZ = index * M;
29781  int levelZ = table->permZ[indexZ];
29782  levelZ = (levelZ / M) * M;
29783  for (j = 0; j < M; j++) {
29784  invpermZ[M * i + j] = table->invpermZ[levelZ + j];
29785  }
29786  }
29787  /* Eliminate dead nodes. Do not scan the cache again, because we
29788  ** assume that Cudd_ReduceHeap has already cleared it.
29789  */
29790  cuddGarbageCollect(table,0);
29791 
29792  result = zddShuffle(table, invpermZ);
29793  FREE(invpermZ);
29794  /* Fix the ZDD variable group tree. */
29795  zddFixTree(table,table->treeZ);
29796  return(result);
29797 
29798 } /* end of cuddZddAlignToBdd */
29799 
29800 
29813 int
29815  DdManager * table,
29816  int x)
29817 {
29818  return(x + 1);
29819 
29820 } /* end of cuddZddNextHigh */
29821 
29822 
29835 int
29837  DdManager * table,
29838  int x)
29839 {
29840  return(x - 1);
29841 
29842 } /* end of cuddZddNextLow */
29843 
29844 
29859 int
29861  int * ptr_x,
29862  int * ptr_y)
29863 {
29864  return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
29865 
29866 } /* end of cuddZddUniqueCompare */
29867 
29868 
29884 int
29886  DdManager * table,
29887  int x,
29888  int y)
29889 {
29890  DdNodePtr *xlist, *ylist;
29891  int xindex, yindex;
29892  int xslots, yslots;
29893  int xshift, yshift;
29894  int oldxkeys, oldykeys;
29895  int newxkeys, newykeys;
29896  int i;
29897  int posn;
29898  DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00;
29899  DdNode *newf1, *newf0, *next;
29900  DdNodePtr g, *lastP, *previousP;
29901 
29902 #ifdef DD_DEBUG
29903  assert(x < y);
29904  assert(cuddZddNextHigh(table,x) == y);
29905  assert(table->subtableZ[x].keys != 0);
29906  assert(table->subtableZ[y].keys != 0);
29907  assert(table->subtableZ[x].dead == 0);
29908  assert(table->subtableZ[y].dead == 0);
29909 #endif
29910 
29912 
29913  /* Get parameters of x subtable. */
29914  xindex = table->invpermZ[x];
29915  xlist = table->subtableZ[x].nodelist;
29916  oldxkeys = table->subtableZ[x].keys;
29917  xslots = table->subtableZ[x].slots;
29918  xshift = table->subtableZ[x].shift;
29919  newxkeys = 0;
29920 
29921  yindex = table->invpermZ[y];
29922  ylist = table->subtableZ[y].nodelist;
29923  oldykeys = table->subtableZ[y].keys;
29924  yslots = table->subtableZ[y].slots;
29925  yshift = table->subtableZ[y].shift;
29926  newykeys = oldykeys;
29927 
29928  /* The nodes in the x layer that don't depend on y directly
29929  ** will stay there; the others are put in a chain.
29930  ** The chain is handled as a FIFO; g points to the beginning and
29931  ** last points to the end.
29932  */
29933 
29934  g = NULL;
29935  lastP = &g;
29936  for (i = 0; i < xslots; i++) {
29937  previousP = &(xlist[i]);
29938  f = *previousP;
29939  while (f != NULL) {
29940  next = f->next;
29941  f1 = cuddT(f); f0 = cuddE(f);
29942  if ((f1->index != (DdHalfWord) yindex) &&
29943  (f0->index != (DdHalfWord) yindex)) { /* stays */
29944  newxkeys++;
29945  *previousP = f;
29946  previousP = &(f->next);
29947  } else {
29948  f->index = yindex;
29949  *lastP = f;
29950  lastP = &(f->next);
29951  }
29952  f = next;
29953  } /* while there are elements in the collision chain */
29954  *previousP = NULL;
29955  } /* for each slot of the x subtable */
29956  *lastP = NULL;
29957 
29958 
29959 #ifdef DD_COUNT
29960  table->swapSteps += oldxkeys - newxkeys;
29961 #endif
29962  /* Take care of the x nodes that must be re-expressed.
29963  ** They form a linked list pointed by g. Their index has been
29964  ** changed to yindex already.
29965  */
29966  f = g;
29967  while (f != NULL) {
29968  next = f->next;
29969  /* Find f1, f0, f11, f10, f01, f00. */
29970  f1 = cuddT(f);
29971  if ((int) f1->index == yindex) {
29972  f11 = cuddT(f1); f10 = cuddE(f1);
29973  } else {
29974  f11 = empty; f10 = f1;
29975  }
29976  f0 = cuddE(f);
29977  if ((int) f0->index == yindex) {
29978  f01 = cuddT(f0); f00 = cuddE(f0);
29979  } else {
29980  f01 = empty; f00 = f0;
29981  }
29982 
29983  /* Decrease ref count of f1. */
29984  cuddSatDec(f1->ref);
29985  /* Create the new T child. */
29986  if (f11 == empty) {
29987  if (f01 != empty) {
29988  newf1 = f01;
29989  cuddSatInc(newf1->ref);
29990  }
29991  /* else case was already handled when finding nodes
29992  ** with both children below level y
29993  */
29994  } else {
29995  /* Check xlist for triple (xindex, f11, f01). */
29996  posn = ddHash(f11, f01, xshift);
29997  /* For each element newf1 in collision list xlist[posn]. */
29998  newf1 = xlist[posn];
29999  while (newf1 != NULL) {
30000  if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
30001  cuddSatInc(newf1->ref);
30002  break; /* match */
30003  }
30004  newf1 = newf1->next;
30005  } /* while newf1 */
30006  if (newf1 == NULL) { /* no match */
30007  newf1 = cuddDynamicAllocNode(table);
30008  if (newf1 == NULL)
30009  goto zddSwapOutOfMem;
30010  newf1->index = xindex; newf1->ref = 1;
30011  cuddT(newf1) = f11;
30012  cuddE(newf1) = f01;
30013  /* Insert newf1 in the collision list xlist[pos];
30014  ** increase the ref counts of f11 and f01
30015  */
30016  newxkeys++;
30017  newf1->next = xlist[posn];
30018  xlist[posn] = newf1;
30019  cuddSatInc(f11->ref);
30020  cuddSatInc(f01->ref);
30021  }
30022  }
30023  cuddT(f) = newf1;
30024 
30025  /* Do the same for f0. */
30026  /* Decrease ref count of f0. */
30027  cuddSatDec(f0->ref);
30028  /* Create the new E child. */
30029  if (f10 == empty) {
30030  newf0 = f00;
30031  cuddSatInc(newf0->ref);
30032  } else {
30033  /* Check xlist for triple (xindex, f10, f00). */
30034  posn = ddHash(f10, f00, xshift);
30035  /* For each element newf0 in collision list xlist[posn]. */
30036  newf0 = xlist[posn];
30037  while (newf0 != NULL) {
30038  if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
30039  cuddSatInc(newf0->ref);
30040  break; /* match */
30041  }
30042  newf0 = newf0->next;
30043  } /* while newf0 */
30044  if (newf0 == NULL) { /* no match */
30045  newf0 = cuddDynamicAllocNode(table);
30046  if (newf0 == NULL)
30047  goto zddSwapOutOfMem;
30048  newf0->index = xindex; newf0->ref = 1;
30049  cuddT(newf0) = f10; cuddE(newf0) = f00;
30050  /* Insert newf0 in the collision list xlist[posn];
30051  ** increase the ref counts of f10 and f00.
30052  */
30053  newxkeys++;
30054  newf0->next = xlist[posn];
30055  xlist[posn] = newf0;
30056  cuddSatInc(f10->ref);
30057  cuddSatInc(f00->ref);
30058  }
30059  }
30060  cuddE(f) = newf0;
30061 
30062  /* Insert the modified f in ylist.
30063  ** The modified f does not already exists in ylist.
30064  ** (Because of the uniqueness of the cofactors.)
30065  */
30066  posn = ddHash(newf1, newf0, yshift);
30067  newykeys++;
30068  f->next = ylist[posn];
30069  ylist[posn] = f;
30070  f = next;
30071  } /* while f != NULL */
30072 
30073  /* GC the y layer. */
30074 
30075  /* For each node f in ylist. */
30076  for (i = 0; i < yslots; i++) {
30077  previousP = &(ylist[i]);
30078  f = *previousP;
30079  while (f != NULL) {
30080  next = f->next;
30081  if (f->ref == 0) {
30082  cuddSatDec(cuddT(f)->ref);
30083  cuddSatDec(cuddE(f)->ref);
30084  cuddDeallocNode(table, f);
30085  newykeys--;
30086  } else {
30087  *previousP = f;
30088  previousP = &(f->next);
30089  }
30090  f = next;
30091  } /* while f */
30092  *previousP = NULL;
30093  } /* for i */
30094 
30095  /* Set the appropriate fields in table. */
30096  table->subtableZ[x].nodelist = ylist;
30097  table->subtableZ[x].slots = yslots;
30098  table->subtableZ[x].shift = yshift;
30099  table->subtableZ[x].keys = newykeys;
30100  table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
30101 
30102  table->subtableZ[y].nodelist = xlist;
30103  table->subtableZ[y].slots = xslots;
30104  table->subtableZ[y].shift = xshift;
30105  table->subtableZ[y].keys = newxkeys;
30106  table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
30107 
30108  table->permZ[xindex] = y; table->permZ[yindex] = x;
30109  table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
30110 
30111  table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
30112 
30113  /* Update univ section; univ[x] remains the same. */
30114  table->univ[y] = cuddT(table->univ[x]);
30115 
30116  return (table->keysZ);
30117 
30118  zddSwapOutOfMem:
30119  (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
30120 
30121  return (0);
30122 
30123 } /* end of cuddZddSwapInPlace */
30124 
30125 
30146 int
30148  DdManager * table,
30149  int lower,
30150  int upper,
30151  Cudd_ReorderingType heuristic)
30152 {
30153  int i, j;
30154  int max, keys;
30155  int nvars;
30156  int x, y;
30157  int iterate;
30158  int previousSize;
30159  Move *moves, *move;
30160  int pivot;
30161  int modulo;
30162  int result;
30163 
30164 #ifdef DD_DEBUG
30165  /* Sanity check */
30166  assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
30167 #endif
30168 
30169  nvars = upper - lower + 1;
30170  iterate = nvars;
30171 
30172  for (i = 0; i < iterate; i++) {
30173  if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
30174  /* Find pivot <= id with maximum keys. */
30175  for (max = -1, j = lower; j <= upper; j++) {
30176  if ((keys = table->subtableZ[j].keys) > max) {
30177  max = keys;
30178  pivot = j;
30179  }
30180  }
30181 
30182  modulo = upper - pivot;
30183  if (modulo == 0) {
30184  y = pivot; /* y = nvars-1 */
30185  } else {
30186  /* y = random # from {pivot+1 .. nvars-1} */
30187  y = pivot + 1 + (int) (Cudd_Random() % modulo);
30188  }
30189 
30190  modulo = pivot - lower - 1;
30191  if (modulo < 1) { /* if pivot = 1 or 0 */
30192  x = lower;
30193  } else {
30194  do { /* x = random # from {0 .. pivot-2} */
30195  x = (int) Cudd_Random() % modulo;
30196  } while (x == y);
30197  /* Is this condition really needed, since x and y
30198  are in regions separated by pivot? */
30199  }
30200  } else {
30201  x = (int) (Cudd_Random() % nvars) + lower;
30202  do {
30203  y = (int) (Cudd_Random() % nvars) + lower;
30204  } while (x == y);
30205  }
30206 
30207  previousSize = table->keysZ;
30208  moves = zddSwapAny(table, x, y);
30209  if (moves == NULL)
30210  goto cuddZddSwappingOutOfMem;
30211 
30212  result = cuddZddSiftingBackward(table, moves, previousSize);
30213  if (!result)
30214  goto cuddZddSwappingOutOfMem;
30215 
30216  while (moves != NULL) {
30217  move = moves->next;
30218  cuddDeallocMove(table, moves);
30219  moves = move;
30220  }
30221 #ifdef DD_STATS
30222  if (table->keysZ < (unsigned) previousSize) {
30223  (void) fprintf(table->out,"-");
30224  } else if (table->keysZ > (unsigned) previousSize) {
30225  (void) fprintf(table->out,"+"); /* should never happen */
30226  } else {
30227  (void) fprintf(table->out,"=");
30228  }
30229  fflush(table->out);
30230 #endif
30231  }
30232 
30233  return(1);
30234 
30235  cuddZddSwappingOutOfMem:
30236  while (moves != NULL) {
30237  move = moves->next;
30238  cuddDeallocMove(table, moves);
30239  moves = move;
30240  }
30241  return(0);
30242 
30243 } /* end of cuddZddSwapping */
30244 
30245 
30267 int
30269  DdManager * table,
30270  int lower,
30271  int upper)
30272 {
30273  int i;
30274  int *var;
30275  int size;
30276  int x;
30277  int result;
30278 #ifdef DD_STATS
30279  int previousSize;
30280 #endif
30281 
30282  size = table->sizeZ;
30283 
30284  /* Find order in which to sift variables. */
30285  var = NULL;
30286  zdd_entry = ALLOC(int, size);
30287  if (zdd_entry == NULL) {
30288  table->errorCode = CUDD_MEMORY_OUT;
30289  goto cuddZddSiftingOutOfMem;
30290  }
30291  var = ALLOC(int, size);
30292  if (var == NULL) {
30293  table->errorCode = CUDD_MEMORY_OUT;
30294  goto cuddZddSiftingOutOfMem;
30295  }
30296 
30297  for (i = 0; i < size; i++) {
30298  x = table->permZ[i];
30299  zdd_entry[i] = table->subtableZ[x].keys;
30300  var[i] = i;
30301  }
30302 
30303  qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
30304 
30305  /* Now sift. */
30306  for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
30307  if (zddTotalNumberSwapping >= table->siftMaxSwap)
30308  break;
30309  if (util_cpu_time() - table->startTime > table->timeLimit) {
30310  table->autoDynZ = 0; /* prevent further reordering */
30311  break;
30312  }
30313  x = table->permZ[var[i]];
30314  if (x < lower || x > upper) continue;
30315 #ifdef DD_STATS
30316  previousSize = table->keysZ;
30317 #endif
30318  result = cuddZddSiftingAux(table, x, lower, upper);
30319  if (!result)
30320  goto cuddZddSiftingOutOfMem;
30321 #ifdef DD_STATS
30322  if (table->keysZ < (unsigned) previousSize) {
30323  (void) fprintf(table->out,"-");
30324  } else if (table->keysZ > (unsigned) previousSize) {
30325  (void) fprintf(table->out,"+"); /* should never happen */
30326  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
30327  } else {
30328  (void) fprintf(table->out,"=");
30329  }
30330  fflush(table->out);
30331 #endif
30332  }
30333 
30334  FREE(var);
30335  FREE(zdd_entry);
30336 
30337  return(1);
30338 
30339  cuddZddSiftingOutOfMem:
30340 
30341  if (zdd_entry != NULL) FREE(zdd_entry);
30342  if (var != NULL) FREE(var);
30343 
30344  return(0);
30345 
30346 } /* end of cuddZddSifting */
30347 
30348 
30349 /*---------------------------------------------------------------------------*/
30350 /* Definition of static functions */
30351 /*---------------------------------------------------------------------------*/
30352 
30353 
30365 static Move *
30367  DdManager * table,
30368  int x,
30369  int y)
30370 {
30371  Move *move, *moves;
30372  int tmp, size;
30373  int x_ref, y_ref;
30374  int x_next, y_next;
30375  int limit_size;
30376 
30377  if (x > y) { /* make x precede y */
30378  tmp = x; x = y; y = tmp;
30379  }
30380 
30381  x_ref = x; y_ref = y;
30382 
30383  x_next = cuddZddNextHigh(table, x);
30384  y_next = cuddZddNextLow(table, y);
30385  moves = NULL;
30386  limit_size = table->keysZ;
30387 
30388  for (;;) {
30389  if (x_next == y_next) { /* x < x_next = y_next < y */
30390  size = cuddZddSwapInPlace(table, x, x_next);
30391  if (size == 0)
30392  goto zddSwapAnyOutOfMem;
30393  move = (Move *) cuddDynamicAllocNode(table);
30394  if (move == NULL)
30395  goto zddSwapAnyOutOfMem;
30396  move->x = x;
30397  move->y = x_next;
30398  move->size = size;
30399  move->next = moves;
30400  moves = move;
30401 
30402  size = cuddZddSwapInPlace(table, y_next, y);
30403  if (size == 0)
30404  goto zddSwapAnyOutOfMem;
30405  move = (Move *)cuddDynamicAllocNode(table);
30406  if (move == NULL)
30407  goto zddSwapAnyOutOfMem;
30408  move->x = y_next;
30409  move->y = y;
30410  move->size = size;
30411  move->next = moves;
30412  moves = move;
30413 
30414  size = cuddZddSwapInPlace(table, x, x_next);
30415  if (size == 0)
30416  goto zddSwapAnyOutOfMem;
30417  move = (Move *)cuddDynamicAllocNode(table);
30418  if (move == NULL)
30419  goto zddSwapAnyOutOfMem;
30420  move->x = x;
30421  move->y = x_next;
30422  move->size = size;
30423  move->next = moves;
30424  moves = move;
30425 
30426  tmp = x; x = y; y = tmp;
30427 
30428  } else if (x == y_next) { /* x = y_next < y = x_next */
30429  size = cuddZddSwapInPlace(table, x, x_next);
30430  if (size == 0)
30431  goto zddSwapAnyOutOfMem;
30432  move = (Move *)cuddDynamicAllocNode(table);
30433  if (move == NULL)
30434  goto zddSwapAnyOutOfMem;
30435  move->x = x;
30436  move->y = x_next;
30437  move->size = size;
30438  move->next = moves;
30439  moves = move;
30440 
30441  tmp = x; x = y; y = tmp;
30442  } else {
30443  size = cuddZddSwapInPlace(table, x, x_next);
30444  if (size == 0)
30445  goto zddSwapAnyOutOfMem;
30446  move = (Move *)cuddDynamicAllocNode(table);
30447  if (move == NULL)
30448  goto zddSwapAnyOutOfMem;
30449  move->x = x;
30450  move->y = x_next;
30451  move->size = size;
30452  move->next = moves;
30453  moves = move;
30454 
30455  size = cuddZddSwapInPlace(table, y_next, y);
30456  if (size == 0)
30457  goto zddSwapAnyOutOfMem;
30458  move = (Move *)cuddDynamicAllocNode(table);
30459  if (move == NULL)
30460  goto zddSwapAnyOutOfMem;
30461  move->x = y_next;
30462  move->y = y;
30463  move->size = size;
30464  move->next = moves;
30465  moves = move;
30466 
30467  x = x_next; y = y_next;
30468  }
30469 
30470  x_next = cuddZddNextHigh(table, x);
30471  y_next = cuddZddNextLow(table, y);
30472  if (x_next > y_ref)
30473  break; /* if x == y_ref */
30474 
30475  if ((double) size > table->maxGrowth * (double) limit_size)
30476  break;
30477  if (size < limit_size)
30478  limit_size = size;
30479  }
30480  if (y_next >= x_ref) {
30481  size = cuddZddSwapInPlace(table, y_next, y);
30482  if (size == 0)
30483  goto zddSwapAnyOutOfMem;
30484  move = (Move *)cuddDynamicAllocNode(table);
30485  if (move == NULL)
30486  goto zddSwapAnyOutOfMem;
30487  move->x = y_next;
30488  move->y = y;
30489  move->size = size;
30490  move->next = moves;
30491  moves = move;
30492  }
30493 
30494  return(moves);
30495 
30496  zddSwapAnyOutOfMem:
30497  while (moves != NULL) {
30498  move = moves->next;
30499  cuddDeallocMove(table, moves);
30500  moves = move;
30501  }
30502  return(NULL);
30503 
30504 } /* end of zddSwapAny */
30505 
30506 
30521 static int
30523  DdManager * table,
30524  int x,
30525  int x_low,
30526  int x_high)
30527 {
30528  Move *move;
30529  Move *moveUp; /* list of up move */
30530  Move *moveDown; /* list of down move */
30531 
30532  int initial_size;
30533  int result;
30534 
30535  initial_size = table->keysZ;
30536 
30537 #ifdef DD_DEBUG
30538  assert(table->subtableZ[x].keys > 0);
30539 #endif
30540 
30541  moveDown = NULL;
30542  moveUp = NULL;
30543 
30544  if (x == x_low) {
30545  moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
30546  /* after that point x --> x_high */
30547  if (moveDown == NULL)
30548  goto cuddZddSiftingAuxOutOfMem;
30549  result = cuddZddSiftingBackward(table, moveDown,
30550  initial_size);
30551  /* move backward and stop at best position */
30552  if (!result)
30553  goto cuddZddSiftingAuxOutOfMem;
30554 
30555  }
30556  else if (x == x_high) {
30557  moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
30558  /* after that point x --> x_low */
30559  if (moveUp == NULL)
30560  goto cuddZddSiftingAuxOutOfMem;
30561  result = cuddZddSiftingBackward(table, moveUp, initial_size);
30562  /* move backward and stop at best position */
30563  if (!result)
30564  goto cuddZddSiftingAuxOutOfMem;
30565  }
30566  else if ((x - x_low) > (x_high - x)) {
30567  /* must go down first:shorter */
30568  moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
30569  /* after that point x --> x_high */
30570  if (moveDown == NULL)
30571  goto cuddZddSiftingAuxOutOfMem;
30572  moveUp = cuddZddSiftingUp(table, moveDown->y, x_low,
30573  initial_size);
30574  if (moveUp == NULL)
30575  goto cuddZddSiftingAuxOutOfMem;
30576  result = cuddZddSiftingBackward(table, moveUp, initial_size);
30577  /* move backward and stop at best position */
30578  if (!result)
30579  goto cuddZddSiftingAuxOutOfMem;
30580  }
30581  else {
30582  moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
30583  /* after that point x --> x_high */
30584  if (moveUp == NULL)
30585  goto cuddZddSiftingAuxOutOfMem;
30586  moveDown = cuddZddSiftingDown(table, moveUp->x, x_high,
30587  initial_size);
30588  /* then move up */
30589  if (moveDown == NULL)
30590  goto cuddZddSiftingAuxOutOfMem;
30591  result = cuddZddSiftingBackward(table, moveDown,
30592  initial_size);
30593  /* move backward and stop at best position */
30594  if (!result)
30595  goto cuddZddSiftingAuxOutOfMem;
30596  }
30597 
30598  while (moveDown != NULL) {
30599  move = moveDown->next;
30600  cuddDeallocMove(table, moveDown);
30601  moveDown = move;
30602  }
30603  while (moveUp != NULL) {
30604  move = moveUp->next;
30605  cuddDeallocMove(table, moveUp);
30606  moveUp = move;
30607  }
30608 
30609  return(1);
30610 
30611  cuddZddSiftingAuxOutOfMem:
30612  while (moveDown != NULL) {
30613  move = moveDown->next;
30614  cuddDeallocMove(table, moveDown);
30615  moveDown = move;
30616  }
30617  while (moveUp != NULL) {
30618  move = moveUp->next;
30619  cuddDeallocMove(table, moveUp);
30620  moveUp = move;
30621  }
30622 
30623  return(0);
30624 
30625 } /* end of cuddZddSiftingAux */
30626 
30627 
30641 static Move *
30643  DdManager * table,
30644  int x,
30645  int x_low,
30646  int initial_size)
30647 {
30648  Move *moves;
30649  Move *move;
30650  int y;
30651  int size;
30652  int limit_size = initial_size;
30653 
30654  moves = NULL;
30655  y = cuddZddNextLow(table, x);
30656  while (y >= x_low) {
30657  size = cuddZddSwapInPlace(table, y, x);
30658  if (size == 0)
30659  goto cuddZddSiftingUpOutOfMem;
30660  move = (Move *)cuddDynamicAllocNode(table);
30661  if (move == NULL)
30662  goto cuddZddSiftingUpOutOfMem;
30663  move->x = y;
30664  move->y = x;
30665  move->size = size;
30666  move->next = moves;
30667  moves = move;
30668 
30669  if ((double)size > (double)limit_size * table->maxGrowth)
30670  break;
30671  if (size < limit_size)
30672  limit_size = size;
30673 
30674  x = y;
30675  y = cuddZddNextLow(table, x);
30676  }
30677  return(moves);
30678 
30679  cuddZddSiftingUpOutOfMem:
30680  while (moves != NULL) {
30681  move = moves->next;
30682  cuddDeallocMove(table, moves);
30683  moves = move;
30684  }
30685  return(NULL);
30686 
30687 } /* end of cuddZddSiftingUp */
30688 
30689 
30704 static Move *
30706  DdManager * table,
30707  int x,
30708  int x_high,
30709  int initial_size)
30710 {
30711  Move *moves;
30712  Move *move;
30713  int y;
30714  int size;
30715  int limit_size = initial_size;
30716 
30717  moves = NULL;
30718  y = cuddZddNextHigh(table, x);
30719  while (y <= x_high) {
30720  size = cuddZddSwapInPlace(table, x, y);
30721  if (size == 0)
30722  goto cuddZddSiftingDownOutOfMem;
30723  move = (Move *)cuddDynamicAllocNode(table);
30724  if (move == NULL)
30725  goto cuddZddSiftingDownOutOfMem;
30726  move->x = x;
30727  move->y = y;
30728  move->size = size;
30729  move->next = moves;
30730  moves = move;
30731 
30732  if ((double)size > (double)limit_size * table->maxGrowth)
30733  break;
30734  if (size < limit_size)
30735  limit_size = size;
30736 
30737  x = y;
30738  y = cuddZddNextHigh(table, x);
30739  }
30740  return(moves);
30741 
30742  cuddZddSiftingDownOutOfMem:
30743  while (moves != NULL) {
30744  move = moves->next;
30745  cuddDeallocMove(table, moves);
30746  moves = move;
30747  }
30748  return(NULL);
30749 
30750 } /* end of cuddZddSiftingDown */
30751 
30752 
30768 static int
30770  DdManager * table,
30771  Move * moves,
30772  int size)
30773 {
30774  int i;
30775  int i_best;
30776  Move *move;
30777  int res;
30778 
30779  /* Find the minimum size among moves. */
30780  i_best = -1;
30781  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
30782  if (move->size < size) {
30783  i_best = i;
30784  size = move->size;
30785  }
30786  }
30787 
30788  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
30789  if (i == i_best)
30790  break;
30791  res = cuddZddSwapInPlace(table, move->x, move->y);
30792  if (!res)
30793  return(0);
30794  if (i_best == -1 && res == size)
30795  break;
30796  }
30797 
30798  return(1);
30799 
30800 } /* end of cuddZddSiftingBackward */
30801 
30802 
30814 static void
30816  DdManager * table)
30817 {
30818 
30819  /* Clear the cache. */
30820  cuddCacheFlush(table);
30821 
30822  /* Eliminate dead nodes. Do not scan the cache again. */
30823  cuddGarbageCollect(table,0);
30824 
30825  return;
30826 
30827 } /* end of ddReorderPreprocess */
30828 
30829 
30843 static int
30845  DdManager * table)
30846 {
30847  int i, j, posn;
30848  DdNodePtr *nodelist, *oldnodelist;
30849  DdNode *node, *next;
30850  unsigned int slots, oldslots;
30851  extern DD_OOMFP MMoutOfMemory;
30852  DD_OOMFP saveHandler;
30853 
30854 #ifdef DD_VERBOSE
30855  (void) fflush(table->out);
30856 #endif
30857 
30858  /* If we have very many reclaimed nodes, we do not want to shrink
30859  ** the subtables, because this will lead to more garbage
30860  ** collections. More garbage collections mean shorter mean life for
30861  ** nodes with zero reference count; hence lower probability of finding
30862  ** a result in the cache.
30863  */
30864  if (table->reclaimed > table->allocated * 0.5) return(1);
30865 
30866  /* Resize subtables. */
30867  for (i = 0; i < table->sizeZ; i++) {
30868  int shift;
30869  oldslots = table->subtableZ[i].slots;
30870  if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY ||
30871  oldslots <= table->initSlots) continue;
30872  oldnodelist = table->subtableZ[i].nodelist;
30873  slots = oldslots >> 1;
30874  saveHandler = MMoutOfMemory;
30875  MMoutOfMemory = Cudd_OutOfMem;
30876  nodelist = ALLOC(DdNodePtr, slots);
30877  MMoutOfMemory = saveHandler;
30878  if (nodelist == NULL) {
30879  return(1);
30880  }
30881  table->subtableZ[i].nodelist = nodelist;
30882  table->subtableZ[i].slots = slots;
30883  table->subtableZ[i].shift++;
30884  table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
30885 #ifdef DD_VERBOSE
30886  (void) fprintf(table->err,
30887  "shrunk layer %d (%d keys) from %d to %d slots\n",
30888  i, table->subtableZ[i].keys, oldslots, slots);
30889 #endif
30890 
30891  for (j = 0; (unsigned) j < slots; j++) {
30892  nodelist[j] = NULL;
30893  }
30894  shift = table->subtableZ[i].shift;
30895  for (j = 0; (unsigned) j < oldslots; j++) {
30896  node = oldnodelist[j];
30897  while (node != NULL) {
30898  next = node->next;
30899  posn = ddHash(cuddT(node), cuddE(node), shift);
30900  node->next = nodelist[posn];
30901  nodelist[posn] = node;
30902  node = next;
30903  }
30904  }
30905  FREE(oldnodelist);
30906 
30907  table->memused += (slots - oldslots) * sizeof(DdNode *);
30908  table->slots += slots - oldslots;
30909  table->minDead = (unsigned) (table->gcFrac * (double) table->slots);
30910  table->cacheSlack = (int) ddMin(table->maxCacheHard,
30912  2 * (int) table->cacheSlots;
30913  }
30914  /* We don't look at the constant subtable, because it is not
30915  ** affected by reordering.
30916  */
30917 
30918  return(1);
30919 
30920 } /* end of zddReorderPostprocess */
30921 
30922 
30938 static int
30940  DdManager * table,
30941  int * permutation)
30942 {
30943  int index;
30944  int level;
30945  int position;
30946  int numvars;
30947  int result;
30948 #ifdef DD_STATS
30949  unsigned long localTime;
30950  int initialSize;
30951  int finalSize;
30952  int previousSize;
30953 #endif
30954 
30956 #ifdef DD_STATS
30957  localTime = util_cpu_time();
30958  initialSize = table->keysZ;
30959  (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
30960  initialSize);
30961 #endif
30962 
30963  numvars = table->sizeZ;
30964 
30965  for (level = 0; level < numvars; level++) {
30966  index = permutation[level];
30967  position = table->permZ[index];
30968 #ifdef DD_STATS
30969  previousSize = table->keysZ;
30970 #endif
30971  result = zddSiftUp(table,position,level);
30972  if (!result) return(0);
30973 #ifdef DD_STATS
30974  if (table->keysZ < (unsigned) previousSize) {
30975  (void) fprintf(table->out,"-");
30976  } else if (table->keysZ > (unsigned) previousSize) {
30977  (void) fprintf(table->out,"+"); /* should never happen */
30978  } else {
30979  (void) fprintf(table->out,"=");
30980  }
30981  fflush(table->out);
30982 #endif
30983  }
30984 
30985 #ifdef DD_STATS
30986  (void) fprintf(table->out,"\n");
30987  finalSize = table->keysZ;
30988  (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
30989  (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
30990  ((double)(util_cpu_time() - localTime)/1000.0));
30991  (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
30993 #endif
30994 
30995  return(1);
30996 
30997 } /* end of zddShuffle */
30998 
30999 
31013 static int
31015  DdManager * table,
31016  int x,
31017  int xLow)
31018 {
31019  int y;
31020  int size;
31021 
31022  y = cuddZddNextLow(table,x);
31023  while (y >= xLow) {
31024  size = cuddZddSwapInPlace(table,y,x);
31025  if (size == 0) {
31026  return(0);
31027  }
31028  x = y;
31029  y = cuddZddNextLow(table,x);
31030  }
31031  return(1);
31032 
31033 } /* end of zddSiftUp */
31034 
31035 
31049 static void
31051  DdManager * table,
31052  MtrNode * treenode)
31053 {
31054  if (treenode == NULL) return;
31055  treenode->low = ((int) treenode->index < table->sizeZ) ?
31056  table->permZ[treenode->index] : treenode->index;
31057  if (treenode->child != NULL) {
31058  zddFixTree(table, treenode->child);
31059  }
31060  if (treenode->younger != NULL)
31061  zddFixTree(table, treenode->younger);
31062  if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
31063  treenode->parent->low = treenode->low;
31064  treenode->parent->index = treenode->index;
31065  }
31066  return;
31067 
31068 } /* end of zddFixTree */
31069 
31146 /*---------------------------------------------------------------------------*/
31147 /* Constant declarations */
31148 /*---------------------------------------------------------------------------*/
31149 
31150 
31151 /*---------------------------------------------------------------------------*/
31152 /* Stucture declarations */
31153 /*---------------------------------------------------------------------------*/
31154 
31155 
31156 /*---------------------------------------------------------------------------*/
31157 /* Type declarations */
31158 /*---------------------------------------------------------------------------*/
31159 
31160 
31161 /*---------------------------------------------------------------------------*/
31162 /* Variable declarations */
31163 /*---------------------------------------------------------------------------*/
31164 
31165 //#ifndef lint
31166 //static char rcsid[] DD_UNUSED = "$Id: cuddZddSetop.c,v 1.26 2012/02/05 01:07:19 fabio Exp $";
31167 //#endif
31168 
31169 /*---------------------------------------------------------------------------*/
31170 /* Macro declarations */
31171 /*---------------------------------------------------------------------------*/
31172 
31173 #ifdef __cplusplus
31174 extern "C" {
31175 #endif
31176 
31179 /*---------------------------------------------------------------------------*/
31180 /* Static function prototypes */
31181 /*---------------------------------------------------------------------------*/
31182 
31183 static DdNode * zdd_subset1_aux (DdManager *zdd, DdNode *P, DdNode *zvar);
31184 static DdNode * zdd_subset0_aux (DdManager *zdd, DdNode *P, DdNode *zvar);
31185 static void zddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty);
31186 
31189 #ifdef __cplusplus
31190 }
31191 #endif
31192 
31193 /*---------------------------------------------------------------------------*/
31194 /* Definition of exported functions */
31195 /*---------------------------------------------------------------------------*/
31196 
31197 
31211 DdNode *
31213  DdManager * zdd,
31214  DdNode * P,
31215  DdNode * Q)
31216 {
31217  int p_top, q_top;
31218  DdNode *empty = DD_ZERO(zdd), *t, *res;
31219  DdManager *table = zdd;
31220 
31221  statLine(zdd);
31222  if (P == empty)
31223  return(empty);
31224  if (Q == empty)
31225  return(P);
31226  if (P == Q)
31227  return(empty);
31228 
31229  /* Check cache. The cache is shared by cuddZddDiff(). */
31230  res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
31231  if (res != NULL)
31232  return(res);
31233 
31234  if (cuddIsConstant(P))
31235  p_top = P->index;
31236  else
31237  p_top = zdd->permZ[P->index];
31238  if (cuddIsConstant(Q))
31239  q_top = Q->index;
31240  else
31241  q_top = zdd->permZ[Q->index];
31242  if (p_top < q_top) {
31243  res = DD_NON_CONSTANT;
31244  } else if (p_top > q_top) {
31245  res = Cudd_zddDiffConst(zdd, P, cuddE(Q));
31246  } else {
31247  t = Cudd_zddDiffConst(zdd, cuddT(P), cuddT(Q));
31248  if (t != empty)
31249  res = DD_NON_CONSTANT;
31250  else
31251  res = Cudd_zddDiffConst(zdd, cuddE(P), cuddE(Q));
31252  }
31253 
31254  cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
31255 
31256  return(res);
31257 
31258 } /* end of Cudd_zddDiffConst */
31259 
31260 
31261 /*---------------------------------------------------------------------------*/
31262 /* Definition of internal functions */
31263 /*---------------------------------------------------------------------------*/
31264 
31265 
31277 DdNode *
31279  DdManager * dd,
31280  DdNode * f,
31281  DdNode * g,
31282  DdNode * h)
31283 {
31284  DdNode *tautology, *empty;
31285  DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e;
31286  unsigned int topf,topg,toph,v,top;
31287  int index;
31288 
31289  statLine(dd);
31290  /* Trivial cases. */
31291  /* One variable cases. */
31292  if (f == (empty = DD_ZERO(dd))) { /* ITE(0,G,H) = H */
31293  return(h);
31294  }
31295  topf = cuddIZ(dd,f->index);
31296  topg = cuddIZ(dd,g->index);
31297  toph = cuddIZ(dd,h->index);
31298  v = ddMin(topg,toph);
31299  top = ddMin(topf,v);
31300 
31301  tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top];
31302  if (f == tautology) { /* ITE(1,G,H) = G */
31303  return(g);
31304  }
31305 
31306  /* From now on, f is known to not be a constant. */
31307  zddVarToConst(f,&g,&h,tautology,empty);
31308 
31309  /* Check remaining one variable cases. */
31310  if (g == h) { /* ITE(F,G,G) = G */
31311  return(g);
31312  }
31313 
31314  if (g == tautology) { /* ITE(F,1,0) = F */
31315  if (h == empty) return(f);
31316  }
31317 
31318  /* Check cache. */
31319  r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h);
31320  if (r != NULL) {
31321  return(r);
31322  }
31323 
31324  /* Recompute these because they may have changed in zddVarToConst. */
31325  topg = cuddIZ(dd,g->index);
31326  toph = cuddIZ(dd,h->index);
31327  v = ddMin(topg,toph);
31328 
31329  if (topf < v) {
31330  r = cuddZddIte(dd,cuddE(f),g,h);
31331  if (r == NULL) return(NULL);
31332  } else if (topf > v) {
31333  if (topg > v) {
31334  Gvn = g;
31335  index = h->index;
31336  } else {
31337  Gvn = cuddE(g);
31338  index = g->index;
31339  }
31340  if (toph > v) {
31341  Hv = empty; Hvn = h;
31342  } else {
31343  Hv = cuddT(h); Hvn = cuddE(h);
31344  }
31345  e = cuddZddIte(dd,f,Gvn,Hvn);
31346  if (e == NULL) return(NULL);
31347  cuddRef(e);
31348  r = cuddZddGetNode(dd,index,Hv,e);
31349  if (r == NULL) {
31350  Cudd_RecursiveDerefZdd(dd,e);
31351  return(NULL);
31352  }
31353  cuddDeref(e);
31354  } else {
31355  index = f->index;
31356  if (topg > v) {
31357  Gv = empty; Gvn = g;
31358  } else {
31359  Gv = cuddT(g); Gvn = cuddE(g);
31360  }
31361  if (toph > v) {
31362  Hv = empty; Hvn = h;
31363  } else {
31364  Hv = cuddT(h); Hvn = cuddE(h);
31365  }
31366  e = cuddZddIte(dd,cuddE(f),Gvn,Hvn);
31367  if (e == NULL) return(NULL);
31368  cuddRef(e);
31369  t = cuddZddIte(dd,cuddT(f),Gv,Hv);
31370  if (t == NULL) {
31371  Cudd_RecursiveDerefZdd(dd,e);
31372  return(NULL);
31373  }
31374  cuddRef(t);
31375  r = cuddZddGetNode(dd,index,t,e);
31376  if (r == NULL) {
31377  Cudd_RecursiveDerefZdd(dd,e);
31378  Cudd_RecursiveDerefZdd(dd,t);
31379  return(NULL);
31380  }
31381  cuddDeref(t);
31382  cuddDeref(e);
31383  }
31384 
31385  cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r);
31386 
31387  return(r);
31388 
31389 } /* end of cuddZddIte */
31390 
31391 
31403 DdNode *
31405  DdManager * zdd,
31406  DdNode * P,
31407  DdNode * Q)
31408 {
31409  int p_top, q_top;
31410  DdNode *empty = DD_ZERO(zdd), *t, *e, *res;
31411  DdManager *table = zdd;
31412 
31413  statLine(zdd);
31414  if (P == empty)
31415  return(Q);
31416  if (Q == empty)
31417  return(P);
31418  if (P == Q)
31419  return(P);
31420 
31421  /* Check cache */
31422  res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q);
31423  if (res != NULL)
31424  return(res);
31425 
31426  if (cuddIsConstant(P))
31427  p_top = P->index;
31428  else
31429  p_top = zdd->permZ[P->index];
31430  if (cuddIsConstant(Q))
31431  q_top = Q->index;
31432  else
31433  q_top = zdd->permZ[Q->index];
31434  if (p_top < q_top) {
31435  e = cuddZddUnion(zdd, cuddE(P), Q);
31436  if (e == NULL) return (NULL);
31437  cuddRef(e);
31438  res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
31439  if (res == NULL) {
31440  Cudd_RecursiveDerefZdd(table, e);
31441  return(NULL);
31442  }
31443  cuddDeref(e);
31444  } else if (p_top > q_top) {
31445  e = cuddZddUnion(zdd, P, cuddE(Q));
31446  if (e == NULL) return(NULL);
31447  cuddRef(e);
31448  res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e);
31449  if (res == NULL) {
31450  Cudd_RecursiveDerefZdd(table, e);
31451  return(NULL);
31452  }
31453  cuddDeref(e);
31454  } else {
31455  t = cuddZddUnion(zdd, cuddT(P), cuddT(Q));
31456  if (t == NULL) return(NULL);
31457  cuddRef(t);
31458  e = cuddZddUnion(zdd, cuddE(P), cuddE(Q));
31459  if (e == NULL) {
31460  Cudd_RecursiveDerefZdd(table, t);
31461  return(NULL);
31462  }
31463  cuddRef(e);
31464  res = cuddZddGetNode(zdd, P->index, t, e);
31465  if (res == NULL) {
31466  Cudd_RecursiveDerefZdd(table, t);
31467  Cudd_RecursiveDerefZdd(table, e);
31468  return(NULL);
31469  }
31470  cuddDeref(t);
31471  cuddDeref(e);
31472  }
31473 
31474  cuddCacheInsert2(table, cuddZddUnion, P, Q, res);
31475 
31476  return(res);
31477 
31478 } /* end of cuddZddUnion */
31479 
31480 
31492 DdNode *
31494  DdManager * zdd,
31495  DdNode * P,
31496  DdNode * Q)
31497 {
31498  int p_top, q_top;
31499  DdNode *empty = DD_ZERO(zdd), *t, *e, *res;
31500  DdManager *table = zdd;
31501 
31502  statLine(zdd);
31503  if (P == empty)
31504  return(empty);
31505  if (Q == empty)
31506  return(empty);
31507  if (P == Q)
31508  return(P);
31509 
31510  /* Check cache. */
31511  res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q);
31512  if (res != NULL)
31513  return(res);
31514 
31515  if (cuddIsConstant(P))
31516  p_top = P->index;
31517  else
31518  p_top = zdd->permZ[P->index];
31519  if (cuddIsConstant(Q))
31520  q_top = Q->index;
31521  else
31522  q_top = zdd->permZ[Q->index];
31523  if (p_top < q_top) {
31524  res = cuddZddIntersect(zdd, cuddE(P), Q);
31525  if (res == NULL) return(NULL);
31526  } else if (p_top > q_top) {
31527  res = cuddZddIntersect(zdd, P, cuddE(Q));
31528  if (res == NULL) return(NULL);
31529  } else {
31530  t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q));
31531  if (t == NULL) return(NULL);
31532  cuddRef(t);
31533  e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q));
31534  if (e == NULL) {
31535  Cudd_RecursiveDerefZdd(table, t);
31536  return(NULL);
31537  }
31538  cuddRef(e);
31539  res = cuddZddGetNode(zdd, P->index, t, e);
31540  if (res == NULL) {
31541  Cudd_RecursiveDerefZdd(table, t);
31542  Cudd_RecursiveDerefZdd(table, e);
31543  return(NULL);
31544  }
31545  cuddDeref(t);
31546  cuddDeref(e);
31547  }
31548 
31549  cuddCacheInsert2(table, cuddZddIntersect, P, Q, res);
31550 
31551  return(res);
31552 
31553 } /* end of cuddZddIntersect */
31554 
31555 
31567 DdNode *
31569  DdManager * zdd,
31570  DdNode * P,
31571  DdNode * Q)
31572 {
31573  int p_top, q_top;
31574  DdNode *empty = DD_ZERO(zdd), *t, *e, *res;
31575  DdManager *table = zdd;
31576 
31577  statLine(zdd);
31578  if (P == empty)
31579  return(empty);
31580  if (Q == empty)
31581  return(P);
31582  if (P == Q)
31583  return(empty);
31584 
31585  /* Check cache. The cache is shared by Cudd_zddDiffConst(). */
31586  res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
31587  if (res != NULL && res != DD_NON_CONSTANT)
31588  return(res);
31589 
31590  if (cuddIsConstant(P))
31591  p_top = P->index;
31592  else
31593  p_top = zdd->permZ[P->index];
31594  if (cuddIsConstant(Q))
31595  q_top = Q->index;
31596  else
31597  q_top = zdd->permZ[Q->index];
31598  if (p_top < q_top) {
31599  e = cuddZddDiff(zdd, cuddE(P), Q);
31600  if (e == NULL) return(NULL);
31601  cuddRef(e);
31602  res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
31603  if (res == NULL) {
31604  Cudd_RecursiveDerefZdd(table, e);
31605  return(NULL);
31606  }
31607  cuddDeref(e);
31608  } else if (p_top > q_top) {
31609  res = cuddZddDiff(zdd, P, cuddE(Q));
31610  if (res == NULL) return(NULL);
31611  } else {
31612  t = cuddZddDiff(zdd, cuddT(P), cuddT(Q));
31613  if (t == NULL) return(NULL);
31614  cuddRef(t);
31615  e = cuddZddDiff(zdd, cuddE(P), cuddE(Q));
31616  if (e == NULL) {
31617  Cudd_RecursiveDerefZdd(table, t);
31618  return(NULL);
31619  }
31620  cuddRef(e);
31621  res = cuddZddGetNode(zdd, P->index, t, e);
31622  if (res == NULL) {
31623  Cudd_RecursiveDerefZdd(table, t);
31624  Cudd_RecursiveDerefZdd(table, e);
31625  return(NULL);
31626  }
31627  cuddDeref(t);
31628  cuddDeref(e);
31629  }
31630 
31631  cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
31632 
31633  return(res);
31634 
31635 } /* end of cuddZddDiff */
31636 
31637 
31649 DdNode *
31651  DdManager * zdd,
31652  DdNode * P,
31653  DdNode * zvar)
31654 {
31655  int top_var, level;
31656  DdNode *res, *t, *e;
31657  DdNode *base = DD_ONE(zdd);
31658  DdNode *empty = DD_ZERO(zdd);
31659 
31660  statLine(zdd);
31661  if (P == empty)
31662  return(empty);
31663  if (P == base)
31664  return(zvar);
31665 
31666  /* Check cache. */
31667  res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar);
31668  if (res != NULL)
31669  return(res);
31670 
31671  top_var = zdd->permZ[P->index];
31672  level = zdd->permZ[zvar->index];
31673 
31674  if (top_var > level) {
31675  res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd));
31676  if (res == NULL) return(NULL);
31677  } else if (top_var == level) {
31678  res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P));
31679  if (res == NULL) return(NULL);
31680  } else {
31681  t = cuddZddChangeAux(zdd, cuddT(P), zvar);
31682  if (t == NULL) return(NULL);
31683  cuddRef(t);
31684  e = cuddZddChangeAux(zdd, cuddE(P), zvar);
31685  if (e == NULL) {
31686  Cudd_RecursiveDerefZdd(zdd, t);
31687  return(NULL);
31688  }
31689  cuddRef(e);
31690  res = cuddZddGetNode(zdd, P->index, t, e);
31691  if (res == NULL) {
31692  Cudd_RecursiveDerefZdd(zdd, t);
31693  Cudd_RecursiveDerefZdd(zdd, e);
31694  return(NULL);
31695  }
31696  cuddDeref(t);
31697  cuddDeref(e);
31698  }
31699 
31700  cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res);
31701 
31702  return(res);
31703 
31704 } /* end of cuddZddChangeAux */
31705 
31706 
31724 DdNode *
31726  DdManager * dd,
31727  DdNode * P,
31728  int var)
31729 {
31730  DdNode *zvar, *r;
31731  DdNode *base, *empty;
31732 
31733  base = DD_ONE(dd);
31734  empty = DD_ZERO(dd);
31735 
31736  zvar = cuddUniqueInterZdd(dd, var, base, empty);
31737  if (zvar == NULL) {
31738  return(NULL);
31739  } else {
31740  cuddRef(zvar);
31741  r = zdd_subset1_aux(dd, P, zvar);
31742  if (r == NULL) {
31743  Cudd_RecursiveDerefZdd(dd, zvar);
31744  return(NULL);
31745  }
31746  cuddRef(r);
31747  Cudd_RecursiveDerefZdd(dd, zvar);
31748  }
31749 
31750  cuddDeref(r);
31751  return(r);
31752 
31753 } /* end of cuddZddSubset1 */
31754 
31755 
31773 DdNode *
31775  DdManager * dd,
31776  DdNode * P,
31777  int var)
31778 {
31779  DdNode *zvar, *r;
31780  DdNode *base, *empty;
31781 
31782  base = DD_ONE(dd);
31783  empty = DD_ZERO(dd);
31784 
31785  zvar = cuddUniqueInterZdd(dd, var, base, empty);
31786  if (zvar == NULL) {
31787  return(NULL);
31788  } else {
31789  cuddRef(zvar);
31790  r = zdd_subset0_aux(dd, P, zvar);
31791  if (r == NULL) {
31792  Cudd_RecursiveDerefZdd(dd, zvar);
31793  return(NULL);
31794  }
31795  cuddRef(r);
31796  Cudd_RecursiveDerefZdd(dd, zvar);
31797  }
31798 
31799  cuddDeref(r);
31800  return(r);
31801 
31802 } /* end of cuddZddSubset0 */
31803 
31804 
31805 /*---------------------------------------------------------------------------*/
31806 /* Definition of static functions */
31807 /*---------------------------------------------------------------------------*/
31808 
31809 
31821 static DdNode *
31823  DdManager * zdd,
31824  DdNode * P,
31825  DdNode * zvar)
31826 {
31827  int top_var, level;
31828  DdNode *res, *t, *e;
31829  DdNode *empty;
31830 
31831  statLine(zdd);
31832  empty = DD_ZERO(zdd);
31833 
31834  /* Check cache. */
31835  res = cuddCacheLookup2Zdd(zdd, zdd_subset1_aux, P, zvar);
31836  if (res != NULL)
31837  return(res);
31838 
31839  if (cuddIsConstant(P)) {
31840  res = empty;
31841  cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res);
31842  return(res);
31843  }
31844 
31845  top_var = zdd->permZ[P->index];
31846  level = zdd->permZ[zvar->index];
31847 
31848  if (top_var > level) {
31849  res = empty;
31850  } else if (top_var == level) {
31851  res = cuddT(P);
31852  } else {
31853  t = zdd_subset1_aux(zdd, cuddT(P), zvar);
31854  if (t == NULL) return(NULL);
31855  cuddRef(t);
31856  e = zdd_subset1_aux(zdd, cuddE(P), zvar);
31857  if (e == NULL) {
31858  Cudd_RecursiveDerefZdd(zdd, t);
31859  return(NULL);
31860  }
31861  cuddRef(e);
31862  res = cuddZddGetNode(zdd, P->index, t, e);
31863  if (res == NULL) {
31864  Cudd_RecursiveDerefZdd(zdd, t);
31865  Cudd_RecursiveDerefZdd(zdd, e);
31866  return(NULL);
31867  }
31868  cuddDeref(t);
31869  cuddDeref(e);
31870  }
31871 
31872  cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res);
31873 
31874  return(res);
31875 
31876 } /* end of zdd_subset1_aux */
31877 
31878 
31890 static DdNode *
31892  DdManager * zdd,
31893  DdNode * P,
31894  DdNode * zvar)
31895 {
31896  int top_var, level;
31897  DdNode *res, *t, *e;
31898 
31899  statLine(zdd);
31900 
31901  /* Check cache. */
31902  res = cuddCacheLookup2Zdd(zdd, zdd_subset0_aux, P, zvar);
31903  if (res != NULL)
31904  return(res);
31905 
31906  if (cuddIsConstant(P)) {
31907  res = P;
31908  cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res);
31909  return(res);
31910  }
31911 
31912  top_var = zdd->permZ[P->index];
31913  level = zdd->permZ[zvar->index];
31914 
31915  if (top_var > level) {
31916  res = P;
31917  }
31918  else if (top_var == level) {
31919  res = cuddE(P);
31920  }
31921  else {
31922  t = zdd_subset0_aux(zdd, cuddT(P), zvar);
31923  if (t == NULL) return(NULL);
31924  cuddRef(t);
31925  e = zdd_subset0_aux(zdd, cuddE(P), zvar);
31926  if (e == NULL) {
31927  Cudd_RecursiveDerefZdd(zdd, t);
31928  return(NULL);
31929  }
31930  cuddRef(e);
31931  res = cuddZddGetNode(zdd, P->index, t, e);
31932  if (res == NULL) {
31933  Cudd_RecursiveDerefZdd(zdd, t);
31934  Cudd_RecursiveDerefZdd(zdd, e);
31935  return(NULL);
31936  }
31937  cuddDeref(t);
31938  cuddDeref(e);
31939  }
31940 
31941  cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res);
31942 
31943  return(res);
31944 
31945 } /* end of zdd_subset0_aux */
31946 
31947 
31960 static void
31962  DdNode * f,
31963  DdNode ** gp,
31964  DdNode ** hp,
31965  DdNode * base,
31966  DdNode * empty)
31967 {
31968  DdNode *g = *gp;
31969  DdNode *h = *hp;
31970 
31971  if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
31972  *gp = base;
31973  }
31974 
31975  if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
31976  *hp = empty;
31977  }
31978 
31979 } /* end of zddVarToConst */
31980 
32051 /*---------------------------------------------------------------------------*/
32052 /* Constant declarations */
32053 /*---------------------------------------------------------------------------*/
32054 
32055 #define ZDD_MV_OOM (Move *)1
32056 
32057 /*---------------------------------------------------------------------------*/
32058 /* Stucture declarations */
32059 /*---------------------------------------------------------------------------*/
32060 
32061 /*---------------------------------------------------------------------------*/
32062 /* Type declarations */
32063 /*---------------------------------------------------------------------------*/
32064 
32065 /*---------------------------------------------------------------------------*/
32066 /* Variable declarations */
32067 /*---------------------------------------------------------------------------*/
32068 
32069 //#ifndef lint
32070 //static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.31 2012/02/05 01:07:19 fabio Exp $";
32071 //#endif
32072 
32073 extern int *zdd_entry;
32074 
32075 extern int zddTotalNumberSwapping;
32076 
32077 static DdNode *empty;
32078 
32079 /*---------------------------------------------------------------------------*/
32080 /* Macro declarations */
32081 /*---------------------------------------------------------------------------*/
32082 
32083 
32086 /*---------------------------------------------------------------------------*/
32087 /* Static function prototypes */
32088 /*---------------------------------------------------------------------------*/
32089 
32090 static int cuddZddSymmSiftingAux (DdManager *table, int x, int x_low, int x_high);
32091 static int cuddZddSymmSiftingConvAux (DdManager *table, int x, int x_low, int x_high);
32092 static Move * cuddZddSymmSifting_up (DdManager *table, int x, int x_low, int initial_size);
32093 static Move * cuddZddSymmSifting_down (DdManager *table, int x, int x_high, int initial_size);
32094 static int cuddZddSymmSiftingBackward (DdManager *table, Move *moves, int size);
32095 static int zdd_group_move (DdManager *table, int x, int y, Move **moves);
32096 static int zdd_group_move_backward (DdManager *table, int x, int y);
32097 static void cuddZddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
32098 
32102 /*---------------------------------------------------------------------------*/
32103 /* Definition of exported functions */
32104 /*---------------------------------------------------------------------------*/
32105 
32106 
32107 
32108 /*---------------------------------------------------------------------------*/
32109 /* Definition of internal functions */
32110 /*---------------------------------------------------------------------------*/
32111 
32112 
32126 int
32128  DdManager * table,
32129  int x,
32130  int y)
32131 {
32132  int i;
32133  DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10;
32134  int yindex;
32135  int xsymmy = 1;
32136  int xsymmyp = 1;
32137  int arccount = 0;
32138  int TotalRefCount = 0;
32139  int symm_found;
32140 
32141  empty = table->zero;
32142 
32143  yindex = table->invpermZ[y];
32144  for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
32145  f = table->subtableZ[x].nodelist[i];
32146  while (f != NULL) {
32147  /* Find f1, f0, f11, f10, f01, f00 */
32148  f1 = cuddT(f);
32149  f0 = cuddE(f);
32150  if ((int) f1->index == yindex) {
32151  f11 = cuddT(f1);
32152  f10 = cuddE(f1);
32153  if (f10 != empty)
32154  arccount++;
32155  } else {
32156  if ((int) f0->index != yindex) {
32157  return(0); /* f bypasses layer y */
32158  }
32159  f11 = empty;
32160  f10 = f1;
32161  }
32162  if ((int) f0->index == yindex) {
32163  f01 = cuddT(f0);
32164  f00 = cuddE(f0);
32165  if (f00 != empty)
32166  arccount++;
32167  } else {
32168  f01 = empty;
32169  f00 = f0;
32170  }
32171  if (f01 != f10)
32172  xsymmy = 0;
32173  if (f11 != f00)
32174  xsymmyp = 0;
32175  if ((xsymmy == 0) && (xsymmyp == 0))
32176  return(0);
32177 
32178  f = f->next;
32179  } /* for each element of the collision list */
32180  } /* for each slot of the subtable */
32181 
32182  /* Calculate the total reference counts of y
32183  ** whose else arc is not empty.
32184  */
32185  for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
32186  f = table->subtableZ[y].nodelist[i];
32187  while (f != NIL(DdNode)) {
32188  if (cuddE(f) != empty)
32189  TotalRefCount += f->ref;
32190  f = f->next;
32191  }
32192  }
32193 
32194  symm_found = (arccount == TotalRefCount);
32195 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
32196  if (symm_found) {
32197  int xindex = table->invpermZ[x];
32198  (void) fprintf(table->out,
32199  "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
32200  xindex,yindex,x,y);
32201  }
32202 #endif
32203 
32204  return(symm_found);
32205 
32206 } /* end cuddZddSymmCheck */
32207 
32208 
32231 int
32233  DdManager * table,
32234  int lower,
32235  int upper)
32236 {
32237  int i;
32238  int *var;
32239  int nvars;
32240  int x;
32241  int result;
32242  int symvars;
32243  int symgroups;
32244  int iteration;
32245 #ifdef DD_STATS
32246  int previousSize;
32247 #endif
32248 
32249  nvars = table->sizeZ;
32250 
32251  /* Find order in which to sift variables. */
32252  var = NULL;
32253  zdd_entry = ALLOC(int, nvars);
32254  if (zdd_entry == NULL) {
32255  table->errorCode = CUDD_MEMORY_OUT;
32256  goto cuddZddSymmSiftingOutOfMem;
32257  }
32258  var = ALLOC(int, nvars);
32259  if (var == NULL) {
32260  table->errorCode = CUDD_MEMORY_OUT;
32261  goto cuddZddSymmSiftingOutOfMem;
32262  }
32263 
32264  for (i = 0; i < nvars; i++) {
32265  x = table->permZ[i];
32266  zdd_entry[i] = table->subtableZ[x].keys;
32267  var[i] = i;
32268  }
32269 
32270  qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
32271 
32272  /* Initialize the symmetry of each subtable to itself. */
32273  for (i = lower; i <= upper; i++)
32274  table->subtableZ[i].next = i;
32275 
32276  iteration = ddMin(table->siftMaxVar, nvars);
32277  for (i = 0; i < iteration; i++) {
32278  if (zddTotalNumberSwapping >= table->siftMaxSwap)
32279  break;
32280  if (util_cpu_time() - table->startTime > table->timeLimit) {
32281  table->autoDynZ = 0; /* prevent further reordering */
32282  break;
32283  }
32284  x = table->permZ[var[i]];
32285 #ifdef DD_STATS
32286  previousSize = table->keysZ;
32287 #endif
32288  if (x < lower || x > upper) continue;
32289  if (table->subtableZ[x].next == (unsigned) x) {
32290  result = cuddZddSymmSiftingAux(table, x, lower, upper);
32291  if (!result)
32292  goto cuddZddSymmSiftingOutOfMem;
32293 #ifdef DD_STATS
32294  if (table->keysZ < (unsigned) previousSize) {
32295  (void) fprintf(table->out,"-");
32296  } else if (table->keysZ > (unsigned) previousSize) {
32297  (void) fprintf(table->out,"+");
32298 #ifdef DD_VERBOSE
32299  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
32300 #endif
32301  } else {
32302  (void) fprintf(table->out,"=");
32303  }
32304  fflush(table->out);
32305 #endif
32306  }
32307  }
32308 
32309  FREE(var);
32310  FREE(zdd_entry);
32311 
32312  cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
32313 
32314 #ifdef DD_STATS
32315  (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
32316  (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
32317 #endif
32318 
32319  return(1+symvars);
32320 
32321  cuddZddSymmSiftingOutOfMem:
32322 
32323  if (zdd_entry != NULL)
32324  FREE(zdd_entry);
32325  if (var != NULL)
32326  FREE(var);
32327 
32328  return(0);
32329 
32330 } /* end of cuddZddSymmSifting */
32331 
32332 
32356 int
32358  DdManager * table,
32359  int lower,
32360  int upper)
32361 {
32362  int i;
32363  int *var;
32364  int nvars;
32365  int initialSize;
32366  int x;
32367  int result;
32368  int symvars;
32369  int symgroups;
32370  int classes;
32371  int iteration;
32372 #ifdef DD_STATS
32373  int previousSize;
32374 #endif
32375 
32376  initialSize = table->keysZ;
32377 
32378  nvars = table->sizeZ;
32379 
32380  /* Find order in which to sift variables. */
32381  var = NULL;
32382  zdd_entry = ALLOC(int, nvars);
32383  if (zdd_entry == NULL) {
32384  table->errorCode = CUDD_MEMORY_OUT;
32385  goto cuddZddSymmSiftingConvOutOfMem;
32386  }
32387  var = ALLOC(int, nvars);
32388  if (var == NULL) {
32389  table->errorCode = CUDD_MEMORY_OUT;
32390  goto cuddZddSymmSiftingConvOutOfMem;
32391  }
32392 
32393  for (i = 0; i < nvars; i++) {
32394  x = table->permZ[i];
32395  zdd_entry[i] = table->subtableZ[x].keys;
32396  var[i] = i;
32397  }
32398 
32399  qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
32400 
32401  /* Initialize the symmetry of each subtable to itself
32402  ** for first pass of converging symmetric sifting.
32403  */
32404  for (i = lower; i <= upper; i++)
32405  table->subtableZ[i].next = i;
32406 
32407  iteration = ddMin(table->siftMaxVar, table->sizeZ);
32408  for (i = 0; i < iteration; i++) {
32409  if (zddTotalNumberSwapping >= table->siftMaxSwap)
32410  break;
32411  if (util_cpu_time() - table->startTime > table->timeLimit) {
32412  table->autoDynZ = 0; /* prevent further reordering */
32413  break;
32414  }
32415  x = table->permZ[var[i]];
32416  if (x < lower || x > upper) continue;
32417  /* Only sift if not in symmetry group already. */
32418  if (table->subtableZ[x].next == (unsigned) x) {
32419 #ifdef DD_STATS
32420  previousSize = table->keysZ;
32421 #endif
32422  result = cuddZddSymmSiftingAux(table, x, lower, upper);
32423  if (!result)
32424  goto cuddZddSymmSiftingConvOutOfMem;
32425 #ifdef DD_STATS
32426  if (table->keysZ < (unsigned) previousSize) {
32427  (void) fprintf(table->out,"-");
32428  } else if (table->keysZ > (unsigned) previousSize) {
32429  (void) fprintf(table->out,"+");
32430 #ifdef DD_VERBOSE
32431  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
32432 #endif
32433  } else {
32434  (void) fprintf(table->out,"=");
32435  }
32436  fflush(table->out);
32437 #endif
32438  }
32439  }
32440 
32441  /* Sifting now until convergence. */
32442  while ((unsigned) initialSize > table->keysZ) {
32443  initialSize = table->keysZ;
32444 #ifdef DD_STATS
32445  (void) fprintf(table->out,"\n");
32446 #endif
32447  /* Here we consider only one representative for each symmetry class. */
32448  for (x = lower, classes = 0; x <= upper; x++, classes++) {
32449  while ((unsigned) x < table->subtableZ[x].next)
32450  x = table->subtableZ[x].next;
32451  /* Here x is the largest index in a group.
32452  ** Groups consists of adjacent variables.
32453  ** Hence, the next increment of x will move it to a new group.
32454  */
32455  i = table->invpermZ[x];
32456  zdd_entry[i] = table->subtableZ[x].keys;
32457  var[classes] = i;
32458  }
32459 
32460  qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare);
32461 
32462  /* Now sift. */
32463  iteration = ddMin(table->siftMaxVar, nvars);
32464  for (i = 0; i < iteration; i++) {
32465  if (zddTotalNumberSwapping >= table->siftMaxSwap)
32466  break;
32467  if (util_cpu_time() - table->startTime > table->timeLimit) {
32468  table->autoDynZ = 0; /* prevent further reordering */
32469  break;
32470  }
32471  x = table->permZ[var[i]];
32472  if ((unsigned) x >= table->subtableZ[x].next) {
32473 #ifdef DD_STATS
32474  previousSize = table->keysZ;
32475 #endif
32476  result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
32477  if (!result)
32478  goto cuddZddSymmSiftingConvOutOfMem;
32479 #ifdef DD_STATS
32480  if (table->keysZ < (unsigned) previousSize) {
32481  (void) fprintf(table->out,"-");
32482  } else if (table->keysZ > (unsigned) previousSize) {
32483  (void) fprintf(table->out,"+");
32484 #ifdef DD_VERBOSE
32485  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
32486 #endif
32487  } else {
32488  (void) fprintf(table->out,"=");
32489  }
32490  fflush(table->out);
32491 #endif
32492  }
32493  } /* for */
32494  }
32495 
32496  cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
32497 
32498 #ifdef DD_STATS
32499  (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
32500  symvars);
32501  (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
32502  symgroups);
32503 #endif
32504 
32505  FREE(var);
32506  FREE(zdd_entry);
32507 
32508  return(1+symvars);
32509 
32510  cuddZddSymmSiftingConvOutOfMem:
32511 
32512  if (zdd_entry != NULL)
32513  FREE(zdd_entry);
32514  if (var != NULL)
32515  FREE(var);
32516 
32517  return(0);
32518 
32519 } /* end of cuddZddSymmSiftingConv */
32520 
32521 
32522 /*---------------------------------------------------------------------------*/
32523 /* Definition of static functions */
32524 /*---------------------------------------------------------------------------*/
32525 
32526 
32542 static int
32544  DdManager * table,
32545  int x,
32546  int x_low,
32547  int x_high)
32548 {
32549  Move *move;
32550  Move *move_up; /* list of up move */
32551  Move *move_down; /* list of down move */
32552  int initial_size;
32553  int result;
32554  int i;
32555  int topbot; /* index to either top or bottom of symmetry group */
32556  int init_group_size, final_group_size;
32557 
32558  initial_size = table->keysZ;
32559 
32560  move_down = NULL;
32561  move_up = NULL;
32562 
32563  /* Look for consecutive symmetries above x. */
32564  for (i = x; i > x_low; i--) {
32565  if (!cuddZddSymmCheck(table, i - 1, i))
32566  break;
32567  /* find top of i-1's symmetry */
32568  topbot = table->subtableZ[i - 1].next;
32569  table->subtableZ[i - 1].next = i;
32570  table->subtableZ[x].next = topbot;
32571  /* x is bottom of group so its symmetry is top of i-1's
32572  group */
32573  i = topbot + 1; /* add 1 for i--, new i is top of symm group */
32574  }
32575  /* Look for consecutive symmetries below x. */
32576  for (i = x; i < x_high; i++) {
32577  if (!cuddZddSymmCheck(table, i, i + 1))
32578  break;
32579  /* find bottom of i+1's symm group */
32580  topbot = i + 1;
32581  while ((unsigned) topbot < table->subtableZ[topbot].next)
32582  topbot = table->subtableZ[topbot].next;
32583 
32584  table->subtableZ[topbot].next = table->subtableZ[i].next;
32585  table->subtableZ[i].next = i + 1;
32586  i = topbot - 1; /* add 1 for i++,
32587  new i is bottom of symm group */
32588  }
32589 
32590  /* Now x maybe in the middle of a symmetry group. */
32591  if (x == x_low) { /* Sift down */
32592  /* Find bottom of x's symm group */
32593  while ((unsigned) x < table->subtableZ[x].next)
32594  x = table->subtableZ[x].next;
32595 
32596  i = table->subtableZ[x].next;
32597  init_group_size = x - i + 1;
32598 
32599  move_down = cuddZddSymmSifting_down(table, x, x_high,
32600  initial_size);
32601  /* after that point x --> x_high, unless early term */
32602  if (move_down == ZDD_MV_OOM)
32603  goto cuddZddSymmSiftingAuxOutOfMem;
32604 
32605  if (move_down == NULL ||
32606  table->subtableZ[move_down->y].next != move_down->y) {
32607  /* symmetry detected may have to make another complete
32608  pass */
32609  if (move_down != NULL)
32610  x = move_down->y;
32611  else
32612  x = table->subtableZ[x].next;
32613  i = x;
32614  while ((unsigned) i < table->subtableZ[i].next) {
32615  i = table->subtableZ[i].next;
32616  }
32617  final_group_size = i - x + 1;
32618 
32619  if (init_group_size == final_group_size) {
32620  /* No new symmetry groups detected,
32621  return to best position */
32622  result = cuddZddSymmSiftingBackward(table,
32623  move_down, initial_size);
32624  }
32625  else {
32626  initial_size = table->keysZ;
32627  move_up = cuddZddSymmSifting_up(table, x, x_low,
32628  initial_size);
32629  result = cuddZddSymmSiftingBackward(table, move_up,
32630  initial_size);
32631  }
32632  }
32633  else {
32634  result = cuddZddSymmSiftingBackward(table, move_down,
32635  initial_size);
32636  /* move backward and stop at best position */
32637  }
32638  if (!result)
32639  goto cuddZddSymmSiftingAuxOutOfMem;
32640  }
32641  else if (x == x_high) { /* Sift up */
32642  /* Find top of x's symm group */
32643  while ((unsigned) x < table->subtableZ[x].next)
32644  x = table->subtableZ[x].next;
32645  x = table->subtableZ[x].next;
32646 
32647  i = x;
32648  while ((unsigned) i < table->subtableZ[i].next) {
32649  i = table->subtableZ[i].next;
32650  }
32651  init_group_size = i - x + 1;
32652 
32653  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
32654  /* after that point x --> x_low, unless early term */
32655  if (move_up == ZDD_MV_OOM)
32656  goto cuddZddSymmSiftingAuxOutOfMem;
32657 
32658  if (move_up == NULL ||
32659  table->subtableZ[move_up->x].next != move_up->x) {
32660  /* symmetry detected may have to make another complete
32661  pass */
32662  if (move_up != NULL)
32663  x = move_up->x;
32664  else {
32665  while ((unsigned) x < table->subtableZ[x].next)
32666  x = table->subtableZ[x].next;
32667  }
32668  i = table->subtableZ[x].next;
32669  final_group_size = x - i + 1;
32670 
32671  if (init_group_size == final_group_size) {
32672  /* No new symmetry groups detected,
32673  return to best position */
32674  result = cuddZddSymmSiftingBackward(table, move_up,
32675  initial_size);
32676  }
32677  else {
32678  initial_size = table->keysZ;
32679  move_down = cuddZddSymmSifting_down(table, x, x_high,
32680  initial_size);
32681  result = cuddZddSymmSiftingBackward(table, move_down,
32682  initial_size);
32683  }
32684  }
32685  else {
32686  result = cuddZddSymmSiftingBackward(table, move_up,
32687  initial_size);
32688  /* move backward and stop at best position */
32689  }
32690  if (!result)
32691  goto cuddZddSymmSiftingAuxOutOfMem;
32692  }
32693  else if ((x - x_low) > (x_high - x)) { /* must go down first:
32694  shorter */
32695  /* Find bottom of x's symm group */
32696  while ((unsigned) x < table->subtableZ[x].next)
32697  x = table->subtableZ[x].next;
32698 
32699  move_down = cuddZddSymmSifting_down(table, x, x_high,
32700  initial_size);
32701  /* after that point x --> x_high, unless early term */
32702  if (move_down == ZDD_MV_OOM)
32703  goto cuddZddSymmSiftingAuxOutOfMem;
32704 
32705  if (move_down != NULL) {
32706  x = move_down->y;
32707  }
32708  else {
32709  x = table->subtableZ[x].next;
32710  }
32711  i = x;
32712  while ((unsigned) i < table->subtableZ[i].next) {
32713  i = table->subtableZ[i].next;
32714  }
32715  init_group_size = i - x + 1;
32716 
32717  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
32718  if (move_up == ZDD_MV_OOM)
32719  goto cuddZddSymmSiftingAuxOutOfMem;
32720 
32721  if (move_up == NULL ||
32722  table->subtableZ[move_up->x].next != move_up->x) {
32723  /* symmetry detected may have to make another complete
32724  pass */
32725  if (move_up != NULL) {
32726  x = move_up->x;
32727  }
32728  else {
32729  while ((unsigned) x < table->subtableZ[x].next)
32730  x = table->subtableZ[x].next;
32731  }
32732  i = table->subtableZ[x].next;
32733  final_group_size = x - i + 1;
32734 
32735  if (init_group_size == final_group_size) {
32736  /* No new symmetry groups detected,
32737  return to best position */
32738  result = cuddZddSymmSiftingBackward(table, move_up,
32739  initial_size);
32740  }
32741  else {
32742  while (move_down != NULL) {
32743  move = move_down->next;
32744  cuddDeallocMove(table, move_down);
32745  move_down = move;
32746  }
32747  initial_size = table->keysZ;
32748  move_down = cuddZddSymmSifting_down(table, x, x_high,
32749  initial_size);
32750  result = cuddZddSymmSiftingBackward(table, move_down,
32751  initial_size);
32752  }
32753  }
32754  else {
32755  result = cuddZddSymmSiftingBackward(table, move_up,
32756  initial_size);
32757  /* move backward and stop at best position */
32758  }
32759  if (!result)
32760  goto cuddZddSymmSiftingAuxOutOfMem;
32761  }
32762  else { /* moving up first:shorter */
32763  /* Find top of x's symmetry group */
32764  while ((unsigned) x < table->subtableZ[x].next)
32765  x = table->subtableZ[x].next;
32766  x = table->subtableZ[x].next;
32767 
32768  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
32769  /* after that point x --> x_high, unless early term */
32770  if (move_up == ZDD_MV_OOM)
32771  goto cuddZddSymmSiftingAuxOutOfMem;
32772 
32773  if (move_up != NULL) {
32774  x = move_up->x;
32775  }
32776  else {
32777  while ((unsigned) x < table->subtableZ[x].next)
32778  x = table->subtableZ[x].next;
32779  }
32780  i = table->subtableZ[x].next;
32781  init_group_size = x - i + 1;
32782 
32783  move_down = cuddZddSymmSifting_down(table, x, x_high,
32784  initial_size);
32785  if (move_down == ZDD_MV_OOM)
32786  goto cuddZddSymmSiftingAuxOutOfMem;
32787 
32788  if (move_down == NULL ||
32789  table->subtableZ[move_down->y].next != move_down->y) {
32790  /* symmetry detected may have to make another complete
32791  pass */
32792  if (move_down != NULL) {
32793  x = move_down->y;
32794  }
32795  else {
32796  x = table->subtableZ[x].next;
32797  }
32798  i = x;
32799  while ((unsigned) i < table->subtableZ[i].next) {
32800  i = table->subtableZ[i].next;
32801  }
32802  final_group_size = i - x + 1;
32803 
32804  if (init_group_size == final_group_size) {
32805  /* No new symmetries detected,
32806  go back to best position */
32807  result = cuddZddSymmSiftingBackward(table, move_down,
32808  initial_size);
32809  }
32810  else {
32811  while (move_up != NULL) {
32812  move = move_up->next;
32813  cuddDeallocMove(table, move_up);
32814  move_up = move;
32815  }
32816  initial_size = table->keysZ;
32817  move_up = cuddZddSymmSifting_up(table, x, x_low,
32818  initial_size);
32819  result = cuddZddSymmSiftingBackward(table, move_up,
32820  initial_size);
32821  }
32822  }
32823  else {
32824  result = cuddZddSymmSiftingBackward(table, move_down,
32825  initial_size);
32826  /* move backward and stop at best position */
32827  }
32828  if (!result)
32829  goto cuddZddSymmSiftingAuxOutOfMem;
32830  }
32831 
32832  while (move_down != NULL) {
32833  move = move_down->next;
32834  cuddDeallocMove(table, move_down);
32835  move_down = move;
32836  }
32837  while (move_up != NULL) {
32838  move = move_up->next;
32839  cuddDeallocMove(table, move_up);
32840  move_up = move;
32841  }
32842 
32843  return(1);
32844 
32845  cuddZddSymmSiftingAuxOutOfMem:
32846  if (move_down != ZDD_MV_OOM) {
32847  while (move_down != NULL) {
32848  move = move_down->next;
32849  cuddDeallocMove(table, move_down);
32850  move_down = move;
32851  }
32852  }
32853  if (move_up != ZDD_MV_OOM) {
32854  while (move_up != NULL) {
32855  move = move_up->next;
32856  cuddDeallocMove(table, move_up);
32857  move_up = move;
32858  }
32859  }
32860 
32861  return(0);
32862 
32863 } /* end of cuddZddSymmSiftingAux */
32864 
32865 
32882 static int
32884  DdManager * table,
32885  int x,
32886  int x_low,
32887  int x_high)
32888 {
32889  Move *move;
32890  Move *move_up; /* list of up move */
32891  Move *move_down; /* list of down move */
32892  int initial_size;
32893  int result;
32894  int i;
32895  int init_group_size, final_group_size;
32896 
32897  initial_size = table->keysZ;
32898 
32899  move_down = NULL;
32900  move_up = NULL;
32901 
32902  if (x == x_low) { /* Sift down */
32903  i = table->subtableZ[x].next;
32904  init_group_size = x - i + 1;
32905 
32906  move_down = cuddZddSymmSifting_down(table, x, x_high,
32907  initial_size);
32908  /* after that point x --> x_high, unless early term */
32909  if (move_down == ZDD_MV_OOM)
32910  goto cuddZddSymmSiftingConvAuxOutOfMem;
32911 
32912  if (move_down == NULL ||
32913  table->subtableZ[move_down->y].next != move_down->y) {
32914  /* symmetry detected may have to make another complete
32915  pass */
32916  if (move_down != NULL)
32917  x = move_down->y;
32918  else {
32919  while ((unsigned) x < table->subtableZ[x].next)
32920  x = table->subtableZ[x].next;
32921  x = table->subtableZ[x].next;
32922  }
32923  i = x;
32924  while ((unsigned) i < table->subtableZ[i].next) {
32925  i = table->subtableZ[i].next;
32926  }
32927  final_group_size = i - x + 1;
32928 
32929  if (init_group_size == final_group_size) {
32930  /* No new symmetries detected,
32931  go back to best position */
32932  result = cuddZddSymmSiftingBackward(table, move_down,
32933  initial_size);
32934  }
32935  else {
32936  initial_size = table->keysZ;
32937  move_up = cuddZddSymmSifting_up(table, x, x_low,
32938  initial_size);
32939  result = cuddZddSymmSiftingBackward(table, move_up,
32940  initial_size);
32941  }
32942  }
32943  else {
32944  result = cuddZddSymmSiftingBackward(table, move_down,
32945  initial_size);
32946  /* move backward and stop at best position */
32947  }
32948  if (!result)
32949  goto cuddZddSymmSiftingConvAuxOutOfMem;
32950  }
32951  else if (x == x_high) { /* Sift up */
32952  /* Find top of x's symm group */
32953  while ((unsigned) x < table->subtableZ[x].next)
32954  x = table->subtableZ[x].next;
32955  x = table->subtableZ[x].next;
32956 
32957  i = x;
32958  while ((unsigned) i < table->subtableZ[i].next) {
32959  i = table->subtableZ[i].next;
32960  }
32961  init_group_size = i - x + 1;
32962 
32963  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
32964  /* after that point x --> x_low, unless early term */
32965  if (move_up == ZDD_MV_OOM)
32966  goto cuddZddSymmSiftingConvAuxOutOfMem;
32967 
32968  if (move_up == NULL ||
32969  table->subtableZ[move_up->x].next != move_up->x) {
32970  /* symmetry detected may have to make another complete
32971  pass */
32972  if (move_up != NULL)
32973  x = move_up->x;
32974  else {
32975  while ((unsigned) x < table->subtableZ[x].next)
32976  x = table->subtableZ[x].next;
32977  }
32978  i = table->subtableZ[x].next;
32979  final_group_size = x - i + 1;
32980 
32981  if (init_group_size == final_group_size) {
32982  /* No new symmetry groups detected,
32983  return to best position */
32984  result = cuddZddSymmSiftingBackward(table, move_up,
32985  initial_size);
32986  }
32987  else {
32988  initial_size = table->keysZ;
32989  move_down = cuddZddSymmSifting_down(table, x, x_high,
32990  initial_size);
32991  result = cuddZddSymmSiftingBackward(table, move_down,
32992  initial_size);
32993  }
32994  }
32995  else {
32996  result = cuddZddSymmSiftingBackward(table, move_up,
32997  initial_size);
32998  /* move backward and stop at best position */
32999  }
33000  if (!result)
33001  goto cuddZddSymmSiftingConvAuxOutOfMem;
33002  }
33003  else if ((x - x_low) > (x_high - x)) { /* must go down first:
33004  shorter */
33005  move_down = cuddZddSymmSifting_down(table, x, x_high,
33006  initial_size);
33007  /* after that point x --> x_high */
33008  if (move_down == ZDD_MV_OOM)
33009  goto cuddZddSymmSiftingConvAuxOutOfMem;
33010 
33011  if (move_down != NULL) {
33012  x = move_down->y;
33013  }
33014  else {
33015  while ((unsigned) x < table->subtableZ[x].next)
33016  x = table->subtableZ[x].next;
33017  x = table->subtableZ[x].next;
33018  }
33019  i = x;
33020  while ((unsigned) i < table->subtableZ[i].next) {
33021  i = table->subtableZ[i].next;
33022  }
33023  init_group_size = i - x + 1;
33024 
33025  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
33026  if (move_up == ZDD_MV_OOM)
33027  goto cuddZddSymmSiftingConvAuxOutOfMem;
33028 
33029  if (move_up == NULL ||
33030  table->subtableZ[move_up->x].next != move_up->x) {
33031  /* symmetry detected may have to make another complete
33032  pass */
33033  if (move_up != NULL) {
33034  x = move_up->x;
33035  }
33036  else {
33037  while ((unsigned) x < table->subtableZ[x].next)
33038  x = table->subtableZ[x].next;
33039  }
33040  i = table->subtableZ[x].next;
33041  final_group_size = x - i + 1;
33042 
33043  if (init_group_size == final_group_size) {
33044  /* No new symmetry groups detected,
33045  return to best position */
33046  result = cuddZddSymmSiftingBackward(table, move_up,
33047  initial_size);
33048  }
33049  else {
33050  while (move_down != NULL) {
33051  move = move_down->next;
33052  cuddDeallocMove(table, move_down);
33053  move_down = move;
33054  }
33055  initial_size = table->keysZ;
33056  move_down = cuddZddSymmSifting_down(table, x, x_high,
33057  initial_size);
33058  result = cuddZddSymmSiftingBackward(table, move_down,
33059  initial_size);
33060  }
33061  }
33062  else {
33063  result = cuddZddSymmSiftingBackward(table, move_up,
33064  initial_size);
33065  /* move backward and stop at best position */
33066  }
33067  if (!result)
33068  goto cuddZddSymmSiftingConvAuxOutOfMem;
33069  }
33070  else { /* moving up first:shorter */
33071  /* Find top of x's symmetry group */
33072  x = table->subtableZ[x].next;
33073 
33074  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
33075  /* after that point x --> x_high, unless early term */
33076  if (move_up == ZDD_MV_OOM)
33077  goto cuddZddSymmSiftingConvAuxOutOfMem;
33078 
33079  if (move_up != NULL) {
33080  x = move_up->x;
33081  }
33082  else {
33083  while ((unsigned) x < table->subtableZ[x].next)
33084  x = table->subtableZ[x].next;
33085  }
33086  i = table->subtableZ[x].next;
33087  init_group_size = x - i + 1;
33088 
33089  move_down = cuddZddSymmSifting_down(table, x, x_high,
33090  initial_size);
33091  if (move_down == ZDD_MV_OOM)
33092  goto cuddZddSymmSiftingConvAuxOutOfMem;
33093 
33094  if (move_down == NULL ||
33095  table->subtableZ[move_down->y].next != move_down->y) {
33096  /* symmetry detected may have to make another complete
33097  pass */
33098  if (move_down != NULL) {
33099  x = move_down->y;
33100  }
33101  else {
33102  while ((unsigned) x < table->subtableZ[x].next)
33103  x = table->subtableZ[x].next;
33104  x = table->subtableZ[x].next;
33105  }
33106  i = x;
33107  while ((unsigned) i < table->subtableZ[i].next) {
33108  i = table->subtableZ[i].next;
33109  }
33110  final_group_size = i - x + 1;
33111 
33112  if (init_group_size == final_group_size) {
33113  /* No new symmetries detected,
33114  go back to best position */
33115  result = cuddZddSymmSiftingBackward(table, move_down,
33116  initial_size);
33117  }
33118  else {
33119  while (move_up != NULL) {
33120  move = move_up->next;
33121  cuddDeallocMove(table, move_up);
33122  move_up = move;
33123  }
33124  initial_size = table->keysZ;
33125  move_up = cuddZddSymmSifting_up(table, x, x_low,
33126  initial_size);
33127  result = cuddZddSymmSiftingBackward(table, move_up,
33128  initial_size);
33129  }
33130  }
33131  else {
33132  result = cuddZddSymmSiftingBackward(table, move_down,
33133  initial_size);
33134  /* move backward and stop at best position */
33135  }
33136  if (!result)
33137  goto cuddZddSymmSiftingConvAuxOutOfMem;
33138  }
33139 
33140  while (move_down != NULL) {
33141  move = move_down->next;
33142  cuddDeallocMove(table, move_down);
33143  move_down = move;
33144  }
33145  while (move_up != NULL) {
33146  move = move_up->next;
33147  cuddDeallocMove(table, move_up);
33148  move_up = move;
33149  }
33150 
33151  return(1);
33152 
33153  cuddZddSymmSiftingConvAuxOutOfMem:
33154  if (move_down != ZDD_MV_OOM) {
33155  while (move_down != NULL) {
33156  move = move_down->next;
33157  cuddDeallocMove(table, move_down);
33158  move_down = move;
33159  }
33160  }
33161  if (move_up != ZDD_MV_OOM) {
33162  while (move_up != NULL) {
33163  move = move_up->next;
33164  cuddDeallocMove(table, move_up);
33165  move_up = move;
33166  }
33167  }
33168 
33169  return(0);
33170 
33171 } /* end of cuddZddSymmSiftingConvAux */
33172 
33173 
33191 static Move *
33193  DdManager * table,
33194  int x,
33195  int x_low,
33196  int initial_size)
33197 {
33198  Move *moves;
33199  Move *move;
33200  int y;
33201  int size;
33202  int limit_size = initial_size;
33203  int i, gytop;
33204 
33205  moves = NULL;
33206  y = cuddZddNextLow(table, x);
33207  while (y >= x_low) {
33208  gytop = table->subtableZ[y].next;
33209  if (cuddZddSymmCheck(table, y, x)) {
33210  /* Symmetry found, attach symm groups */
33211  table->subtableZ[y].next = x;
33212  i = table->subtableZ[x].next;
33213  while (table->subtableZ[i].next != (unsigned) x)
33214  i = table->subtableZ[i].next;
33215  table->subtableZ[i].next = gytop;
33216  }
33217  else if ((table->subtableZ[x].next == (unsigned) x) &&
33218  (table->subtableZ[y].next == (unsigned) y)) {
33219  /* x and y have self symmetry */
33220  size = cuddZddSwapInPlace(table, y, x);
33221  if (size == 0)
33222  goto cuddZddSymmSifting_upOutOfMem;
33223  move = (Move *)cuddDynamicAllocNode(table);
33224  if (move == NULL)
33225  goto cuddZddSymmSifting_upOutOfMem;
33226  move->x = y;
33227  move->y = x;
33228  move->size = size;
33229  move->next = moves;
33230  moves = move;
33231  if ((double)size >
33232  (double)limit_size * table->maxGrowth)
33233  return(moves);
33234  if (size < limit_size)
33235  limit_size = size;
33236  }
33237  else { /* Group move */
33238  size = zdd_group_move(table, y, x, &moves);
33239  if ((double)size >
33240  (double)limit_size * table->maxGrowth)
33241  return(moves);
33242  if (size < limit_size)
33243  limit_size = size;
33244  }
33245  x = gytop;
33246  y = cuddZddNextLow(table, x);
33247  }
33248 
33249  return(moves);
33250 
33251  cuddZddSymmSifting_upOutOfMem:
33252  while (moves != NULL) {
33253  move = moves->next;
33254  cuddDeallocMove(table, moves);
33255  moves = move;
33256  }
33257  return(ZDD_MV_OOM);
33258 
33259 } /* end of cuddZddSymmSifting_up */
33260 
33261 
33279 static Move *
33281  DdManager * table,
33282  int x,
33283  int x_high,
33284  int initial_size)
33285 {
33286  Move *moves;
33287  Move *move;
33288  int y;
33289  int size;
33290  int limit_size = initial_size;
33291  int i, gxtop, gybot;
33292 
33293  moves = NULL;
33294  y = cuddZddNextHigh(table, x);
33295  while (y <= x_high) {
33296  gybot = table->subtableZ[y].next;
33297  while (table->subtableZ[gybot].next != (unsigned) y)
33298  gybot = table->subtableZ[gybot].next;
33299  if (cuddZddSymmCheck(table, x, y)) {
33300  /* Symmetry found, attach symm groups */
33301  gxtop = table->subtableZ[x].next;
33302  table->subtableZ[x].next = y;
33303  i = table->subtableZ[y].next;
33304  while (table->subtableZ[i].next != (unsigned) y)
33305  i = table->subtableZ[i].next;
33306  table->subtableZ[i].next = gxtop;
33307  }
33308  else if ((table->subtableZ[x].next == (unsigned) x) &&
33309  (table->subtableZ[y].next == (unsigned) y)) {
33310  /* x and y have self symmetry */
33311  size = cuddZddSwapInPlace(table, x, y);
33312  if (size == 0)
33313  goto cuddZddSymmSifting_downOutOfMem;
33314  move = (Move *)cuddDynamicAllocNode(table);
33315  if (move == NULL)
33316  goto cuddZddSymmSifting_downOutOfMem;
33317  move->x = x;
33318  move->y = y;
33319  move->size = size;
33320  move->next = moves;
33321  moves = move;
33322  if ((double)size >
33323  (double)limit_size * table->maxGrowth)
33324  return(moves);
33325  if (size < limit_size)
33326  limit_size = size;
33327  x = y;
33328  y = cuddZddNextHigh(table, x);
33329  }
33330  else { /* Group move */
33331  size = zdd_group_move(table, x, y, &moves);
33332  if ((double)size >
33333  (double)limit_size * table->maxGrowth)
33334  return(moves);
33335  if (size < limit_size)
33336  limit_size = size;
33337  }
33338  x = gybot;
33339  y = cuddZddNextHigh(table, x);
33340  }
33341 
33342  return(moves);
33343 
33344  cuddZddSymmSifting_downOutOfMem:
33345  while (moves != NULL) {
33346  move = moves->next;
33347  cuddDeallocMove(table, moves);
33348  moves = move;
33349  }
33350  return(ZDD_MV_OOM);
33351 
33352 } /* end of cuddZddSymmSifting_down */
33353 
33354 
33370 static int
33372  DdManager * table,
33373  Move * moves,
33374  int size)
33375 {
33376  int i;
33377  int i_best;
33378  Move *move;
33379  int res;
33380 
33381  i_best = -1;
33382  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
33383  if (move->size < size) {
33384  i_best = i;
33385  size = move->size;
33386  }
33387  }
33388 
33389  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
33390  if (i == i_best) break;
33391  if ((table->subtableZ[move->x].next == move->x) &&
33392  (table->subtableZ[move->y].next == move->y)) {
33393  res = cuddZddSwapInPlace(table, move->x, move->y);
33394  if (!res) return(0);
33395  }
33396  else { /* Group move necessary */
33397  res = zdd_group_move_backward(table, move->x, move->y);
33398  }
33399  if (i_best == -1 && res == size)
33400  break;
33401  }
33402 
33403  return(1);
33404 
33405 } /* end of cuddZddSymmSiftingBackward */
33406 
33407 
33422 static int
33424  DdManager * table,
33425  int x,
33426  int y,
33427  Move ** moves)
33428 {
33429  Move *move;
33430  int size;
33431  int i, temp, gxtop, gxbot, gybot, yprev;
33432  int swapx, swapy;
33433 
33434 #ifdef DD_DEBUG
33435  assert(x < y); /* we assume that x < y */
33436 #endif
33437  /* Find top and bottom for the two groups. */
33438  gxtop = table->subtableZ[x].next;
33439  gxbot = x;
33440  gybot = table->subtableZ[y].next;
33441  while (table->subtableZ[gybot].next != (unsigned) y)
33442  gybot = table->subtableZ[gybot].next;
33443  yprev = gybot;
33444 
33445  while (x <= y) {
33446  while (y > gxtop) {
33447  /* Set correct symmetries. */
33448  temp = table->subtableZ[x].next;
33449  if (temp == x)
33450  temp = y;
33451  i = gxtop;
33452  for (;;) {
33453  if (table->subtableZ[i].next == (unsigned) x) {
33454  table->subtableZ[i].next = y;
33455  break;
33456  } else {
33457  i = table->subtableZ[i].next;
33458  }
33459  }
33460  if (table->subtableZ[y].next != (unsigned) y) {
33461  table->subtableZ[x].next = table->subtableZ[y].next;
33462  } else {
33463  table->subtableZ[x].next = x;
33464  }
33465 
33466  if (yprev != y) {
33467  table->subtableZ[yprev].next = x;
33468  } else {
33469  yprev = x;
33470  }
33471  table->subtableZ[y].next = temp;
33472 
33473  size = cuddZddSwapInPlace(table, x, y);
33474  if (size == 0)
33475  goto zdd_group_moveOutOfMem;
33476  swapx = x;
33477  swapy = y;
33478  y = x;
33479  x--;
33480  } /* while y > gxtop */
33481 
33482  /* Trying to find the next y. */
33483  if (table->subtableZ[y].next <= (unsigned) y) {
33484  gybot = y;
33485  } else {
33486  y = table->subtableZ[y].next;
33487  }
33488 
33489  yprev = gxtop;
33490  gxtop++;
33491  gxbot++;
33492  x = gxbot;
33493  } /* while x <= y, end of group movement */
33494  move = (Move *)cuddDynamicAllocNode(table);
33495  if (move == NULL)
33496  goto zdd_group_moveOutOfMem;
33497  move->x = swapx;
33498  move->y = swapy;
33499  move->size = table->keysZ;
33500  move->next = *moves;
33501  *moves = move;
33502 
33503  return(table->keysZ);
33504 
33505  zdd_group_moveOutOfMem:
33506  while (*moves != NULL) {
33507  move = (*moves)->next;
33508  cuddDeallocMove(table, *moves);
33509  *moves = move;
33510  }
33511  return(0);
33512 
33513 } /* end of zdd_group_move */
33514 
33515 
33529 static int
33531  DdManager * table,
33532  int x,
33533  int y)
33534 {
33535  int size;
33536  int i, temp, gxtop, gxbot, gybot, yprev;
33537 
33538 #ifdef DD_DEBUG
33539  assert(x < y); /* we assume that x < y */
33540 #endif
33541  /* Find top and bottom of the two groups. */
33542  gxtop = table->subtableZ[x].next;
33543  gxbot = x;
33544  gybot = table->subtableZ[y].next;
33545  while (table->subtableZ[gybot].next != (unsigned) y)
33546  gybot = table->subtableZ[gybot].next;
33547  yprev = gybot;
33548 
33549  while (x <= y) {
33550  while (y > gxtop) {
33551  /* Set correct symmetries. */
33552  temp = table->subtableZ[x].next;
33553  if (temp == x)
33554  temp = y;
33555  i = gxtop;
33556  for (;;) {
33557  if (table->subtableZ[i].next == (unsigned) x) {
33558  table->subtableZ[i].next = y;
33559  break;
33560  } else {
33561  i = table->subtableZ[i].next;
33562  }
33563  }
33564  if (table->subtableZ[y].next != (unsigned) y) {
33565  table->subtableZ[x].next = table->subtableZ[y].next;
33566  } else {
33567  table->subtableZ[x].next = x;
33568  }
33569 
33570  if (yprev != y) {
33571  table->subtableZ[yprev].next = x;
33572  } else {
33573  yprev = x;
33574  }
33575  table->subtableZ[y].next = temp;
33576 
33577  size = cuddZddSwapInPlace(table, x, y);
33578  if (size == 0)
33579  return(0);
33580  y = x;
33581  x--;
33582  } /* while y > gxtop */
33583 
33584  /* Trying to find the next y. */
33585  if (table->subtableZ[y].next <= (unsigned) y) {
33586  gybot = y;
33587  } else {
33588  y = table->subtableZ[y].next;
33589  }
33590 
33591  yprev = gxtop;
33592  gxtop++;
33593  gxbot++;
33594  x = gxbot;
33595  } /* while x <= y, end of group movement backward */
33596 
33597  return(size);
33598 
33599 } /* end of zdd_group_move_backward */
33600 
33601 
33612 static void
33614  DdManager * table,
33615  int lower,
33616  int upper,
33617  int * symvars,
33618  int * symgroups)
33619 {
33620  int i,x,gbot;
33621  int TotalSymm = 0;
33622  int TotalSymmGroups = 0;
33623 
33624  for (i = lower; i <= upper; i++) {
33625  if (table->subtableZ[i].next != (unsigned) i) {
33626  TotalSymmGroups++;
33627  x = i;
33628  do {
33629  TotalSymm++;
33630  gbot = x;
33631  x = table->subtableZ[x].next;
33632  } while (x != i);
33633 #ifdef DD_DEBUG
33634  assert(table->subtableZ[gbot].next == (unsigned) i);
33635 #endif
33636  i = gbot;
33637  }
33638  }
33639  *symvars = TotalSymm;
33640  *symgroups = TotalSymmGroups;
33641 
33642  return;
33643 
33644 } /* end of cuddZddSymmSummary */
33645 
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddInt.c:29814
static int ddSiftUp2(DdManager *table, int x, int xLow)
Definition: cuddInt.c:16295
static void zddMergeGroups(DdManager *table, MtrNode *treenode, int low, int high)
Definition: cuddInt.c:27636
void cuddCacheInsert1(DdManager *table, DD_CTFP1 op, DdNode *f, DdNode *data)
Definition: cuddInt.c:4371
unsigned int keysize
Definition: cuddInt.h:289
static int getMaxBinomial(int n)
Definition: cuddInt.c:6684
DdHalfWord ref
Definition: cudd.h:266
static void cuddXorLinear(DdManager *table, int x, int y)
Definition: cuddInt.c:13863
DdNode * Cudd_bddAnd(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:3114
static Move * cuddZddSymmSifting_up(DdManager *table, int x, int x_low, int initial_size)
Definition: cuddInt.c:33192
#define DD_MAXREF
Definition: cuddInt.h:101
#define MTR_TERMINAL
Definition: mtr.h:95
static int make_random(DdManager *table, int lower)
Definition: cuddInt.c:7793
DdNode * cuddConstantLookup(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:4756
int Cudd_EquivDC(DdManager *dd, DdNode *F, DdNode *G, DdNode *D)
Definition: cuddInt.c:16770
static void ddPrintMintermAux(DdManager *dd, DdNode *node, int *list)
Definition: cuddInt.c:23199
#define cuddRef(n)
Definition: cuddInt.h:557
Cudd_AggregationType groupcheck
Definition: cuddInt.h:410
DdNode * cuddBddExistAbstractRecur(DdManager *manager, DdNode *f, DdNode *cube)
Definition: cuddInt.c:2437
DdNode * node
Definition: cuddInt.h:227
int cuddBddAlignToZdd(DdManager *table)
Definition: cuddInt.c:15572
static void copyOrder(DdManager *table, int *array, int lower, int upper)
Definition: cuddInt.c:1365
unsigned int keys
Definition: cuddInt.h:314
MtrHalfWord flags
Definition: mtr.h:127
DdHashItem ** bucket
Definition: cuddInt.h:291
static int siftBackwardProb(DdManager *table, Move *moves, int size, double temp)
Definition: cuddInt.c:1301
int ptrint
Definition: cuddInt.h:249
#define CUDD_OUT_OF_MEM
Definition: cudd.h:88
int cuddZddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddInt.c:26558
#define Cudd_T(node)
Definition: cudd.h:416
unsigned short DdHalfWord
Definition: cudd.h:253
static Move * ddUndoMoves(DdManager *table, Move *moves)
Definition: cuddInt.c:13798
static void zddFixTree(DdManager *table, MtrNode *treenode)
Definition: cuddInt.c:31050
#define BDCA
#define DCBA
#define DD_SIFT_UP
Definition: cuddInt.c:8396
#define ACBD
VOID_OR_INT exit()
int type
Definition: cuddInt.h:208
void EpdMultiply(EpDouble *epd1, double value)
Definition: epd.c:130
DdGen * Cudd_FirstNode(DdManager *dd, DdNode *f, DdNode **node)
Definition: cuddInt.c:22723
DdNode * cuddAllocNode(DdManager *unique)
Definition: cuddInt.c:19624
#define DD_MAX_HASHTABLE_DENSITY
Definition: cuddInt.c:11244
static int ddReorderChildren(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddInt.c:8689
DdNode * value
Definition: cuddInt.h:283
static int ddShuffle(DdManager *table, DdHalfWord *permutation, int lower, int upper)
Definition: cuddInt.c:6862
static int ddUniqueCompareGroup(int *ptrX, int *ptrY)
Definition: cuddInt.c:8928
#define ddHash(f, g, s)
Definition: cuddInt.h:696
unsigned int size
Definition: cuddInt.h:296
#define LEQA2
Definition: cuddInt.c:22118
union DdNode::@0 type
static Move * cuddZddUndoMoves(DdManager *table, Move *moves)
Definition: cuddInt.c:29394
void EpdFree(EpDouble *epd)
Definition: epd.c:92
int st_lookup(st_table *, void *, void *)
Definition: st.c:271
#define cuddDeref(n)
Definition: cuddInt.h:577
static int zddGroupSiftingDown(DdManager *table, int x, int xHigh, Move **moves)
Definition: cuddInt.c:27322
Definition: st.h:60
DdNode * Cudd_bddXor(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:3253
void cuddUpdateInteractionMatrix(DdManager *table, int xindex, int yindex)
Definition: cuddInt.c:13228
static double ddCountPathsToNonZero(DdNode *N, st_table *table)
Definition: cuddInt.c:23733
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
unsigned long reordTime
Definition: cuddInt.h:434
Cudd_AggregationType
Definition: cudd.h:174
#define Cudd_E(node)
Definition: cudd.h:431
DdNode * Cudd_addIteConstant(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:128
static int ddLeavesInt(DdNode *n)
Definition: cuddInt.c:23852
Cudd_ReorderingType autoMethod
Definition: cuddInt.h:402
static Move * ddJumpingDown(DdManager *table, int x, int x_high, int initial_size)
Definition: cuddInt.c:1241
DdNode * cuddUniqueInter(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddInt.c:20495
#define cuddIZ(dd, index)
Definition: cuddInt.h:677
static int ddGroupSifting(DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag)
Definition: cuddInt.c:8956
static DdHalfWord ** getMatrix(int rows, int cols)
Definition: cuddInt.c:6772
#define DD_SIFT_MAX_VAR
Definition: cuddInt.h:148
unsigned int peakLiveNodes
Definition: cuddInt.h:445
static void bddVarToConst(DdNode *f, DdNode **gp, DdNode **hp, DdNode *one)
Definition: cuddInt.c:3882
int maxSizeZ
Definition: cuddInt.h:348
double allocated
Definition: cuddInt.h:365
static void ddMergeGroups(DdManager *table, MtrNode *treenode, int low, int high)
Definition: cuddInt.c:10016
static int ddDagInt(DdNode *n)
Definition: cuddInt.c:23253
static int zddGroupSiftingBackward(DdManager *table, Move *moves, int size)
Definition: cuddInt.c:27588
DdNode * f
Definition: cuddInt.h:302
int * map
Definition: cuddInt.h:374
int st_lookup_int(st_table *, void *, int *)
Definition: st.c:307
#define LEQQ1
Definition: cuddInt.c:22115
Definition: cudd.h:264
DdNode * cuddCacheLookupZdd(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:4475
static DD_INLINE DdHashItem * cuddHashTableAlloc(DdHashTable *hash)
Definition: cuddInt.c:12494
#define Cudd_Not(node)
Definition: cudd.h:343
DdNode * Cudd_bddIte(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:2942
#define DD_MAX_CACHE_FRACTION
Definition: cuddInt.h:141
unsigned int deadZ
Definition: cuddInt.h:356
static int ddLinearAndSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddInt.c:13410
MtrHalfWord size
Definition: mtr.h:129
#define FREE(obj)
Definition: util.h:80
DdNode * Cudd_addCmpl(DdManager *dd, DdNode *f)
Definition: cuddInt.c:312
#define BDAC
DdNode * data
Definition: cuddInt.h:304
#define BCA
static int ddExchange(DdManager *table, int x, int y, double temp)
Definition: cuddInt.c:962
DdNode * cuddCacheLookup(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:4413
#define ddLCHash3(f, g, h, shift)
Definition: cuddInt.c:11320
void st_free_gen(st_generator *)
Definition: st.c:730
DdManager * Cudd_Init(unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory)
Definition: cuddInt.c:10544
#define CUDD_GEN_ZDD_PATHS
Definition: cuddInt.h:197
#define CADB
int siftMaxSwap
Definition: cuddInt.h:396
int st_foreach(st_table *, ST_PFSR, char *)
Definition: st.c:487
#define DBAC
#define LEQR1
Definition: cuddInt.c:22116
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:302
void cuddShrinkDeathRow(DdManager *table)
Definition: cuddInt.c:14327
static DD_INLINE void ddFixLimits(DdManager *unique)
Definition: cuddInt.c:21624
DdHook * preReorderingHook
Definition: cuddInt.h:421
unsigned deadMask
Definition: cuddInt.h:387
unsigned long startTime
Definition: cuddInt.h:426
static double ddCountMintermAux(DdNode *node, double max, DdHashTable *table)
Definition: cuddInt.c:23527
static Move * cuddZddSiftingUp(DdManager *table, int x, int x_low, int initial_size)
Definition: cuddInt.c:30642
#define CAB
static enum st_retval freePathPair(char *key, char *value, char *arg)
Definition: cuddInt.c:17213
int * invpermZ
Definition: cuddInt.h:372
Definition: st.h:78
int reordCycle
Definition: cuddInt.h:399
int * zdd_entry
Definition: cuddInt.c:29545
#define ADCB
unsigned int bits[2]
Definition: cuddInt.c:19539
DdNode * cuddCacheLookup1(DdManager *table, DD_CTFP1 op, DdNode *f)
Definition: cuddInt.c:4591
int cuddCollectNodes(DdNode *f, st_table *visited)
Definition: cuddInt.c:23013
#define assert(ex)
Definition: util.h:141
#define ALPHA
Definition: cuddInt.c:681
int cuddHashTableInsert1(DdHashTable *hash, DdNode *f, DdNode *value, ptrint count)
Definition: cuddInt.c:11803
void cuddHashTableGenericQuit(DdHashTable *hash)
Definition: cuddInt.c:11643
int cuddInitInteract(DdManager *table)
Definition: cuddInt.c:10963
static Move * ddSiftingDown(DdManager *table, int x, int xHigh)
Definition: cuddInt.c:16016
static int ddSymmGroupMove(DdManager *table, int x, int y, Move **moves)
Definition: cuddInt.c:19204
DdManager * manager
Definition: cuddInt.h:298
#define DD_BDD_ITE_CONSTANT_TAG
Definition: cuddInt.h:187
int Cudd_BddToCubeArray(DdManager *dd, DdNode *cube, int *array)
Definition: cuddInt.c:22669
#define CBDA
static Move * cuddZddSiftingDown(DdManager *table, int x, int x_high, int initial_size)
Definition: cuddInt.c:30705
#define CUDD_GEN_NODES
Definition: cuddInt.h:196
static unsigned int originalSize
Definition: cuddInt.c:8436
int size
Definition: cuddInt.h:345
#define DABC
double gcFrac
Definition: cuddInt.h:359
static void pushDown(DdHalfWord *order, int j, int level)
Definition: cuddInt.c:7255
union hack hack
static DdNode * one
Definition: cuddInt.c:16562
#define DD_STASH_FRACTION
Definition: cuddInt.h:143
char * memcpy()
DdNode * Cudd_ReadLogicZero(DdManager *dd)
Definition: cuddInt.c:1738
static char rcsid [] DD_UNUSED
Definition: cuddInt.c:86
#define DD_ADD_ITE_CONSTANT_TAG
Definition: cuddInt.h:185
void st_free_table(st_table *)
Definition: st.c:237
Definition: cuddInt.h:469
struct DdManager DdManager
Definition: cudd.h:274
#define Cudd_IsConstant(node)
Definition: cudd.h:328
unsigned int maxCacheHard
Definition: cuddInt.h:343
static int zddSiftUp(DdManager *table, int x, int xLow)
Definition: cuddInt.c:31014
#define BPL
Definition: cuddInt.c:12624
int cuddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddInt.c:8507
struct DdGen::@1::@5 nodes
unsigned int slots
Definition: cuddInt.h:352
ptruint h
Definition: cuddInt.h:303
DdNode * cuddUniqueConst(DdManager *unique, CUDD_VALUE_TYPE value)
Definition: cuddInt.c:20837
DdNode * zero
Definition: cuddInt.h:330
static int bddVarToCanonicalSimple(DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp)
Definition: cuddInt.c:4019
#define Cudd_Regular(node)
Definition: cudd.h:373
static int zdd_group_move(DdManager *table, int x, int y, Move **moves)
Definition: cuddInt.c:33423
#define DD_MAX_LOOSE_FRACTION
Definition: cuddInt.h:139
DdNode * cuddBddIsop(DdManager *dd, DdNode *L, DdNode *U)
Definition: cuddInt.c:28135
int cuddZddGetCofactors3(DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0, DdNode **fd)
Definition: cuddInt.c:26127
double maxGrowthAlt
Definition: cuddInt.h:398
static int bddVarToCanonical(DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp)
Definition: cuddInt.c:3917
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddInt.c:14727
ptrint count
Definition: cuddInt.h:282
int realign
Definition: cuddInt.h:404
static DdNode * empty
Definition: cuddInt.c:28567
static void ddSuppInteract(DdNode *f, char *support)
Definition: cuddInt.c:11043
double maxGrowth
Definition: cuddInt.h:397
#define BCDA
static int ddWindow2(DdManager *table, int low, int high)
Definition: cuddInt.c:24195
static int ddGroupSiftingAux(DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag)
Definition: cuddInt.c:9197
DdNode * cuddHashTableLookup(DdHashTable *hash, DdNodePtr *key)
Definition: cuddInt.c:11739
DdNode * Cudd_LargestCube(DdManager *manager, DdNode *f, int *length)
Definition: cuddInt.c:16616
int st_gen(st_generator *, void *, void *)
Definition: st.c:644
static int ddUniqueCompare(int *ptrX, int *ptrY)
Definition: cuddInt.c:15644
static int ddGroupSiftingBackward(DdManager *table, Move *moves, int size, int upFlag, int lazyFlag)
Definition: cuddInt.c:9909
FILE * err
Definition: cuddInt.h:424
static void ddClearLocal(DdNode *f)
Definition: cuddInt.c:11074
DdNode * g
Definition: cuddInt.h:302
#define ABCD
int cuddSymmSiftingConv(DdManager *table, int lower, int upper)
Definition: cuddInt.c:18163
int Cudd_ReduceHeap(DdManager *table, Cudd_ReorderingType heuristic, int minsize)
Definition: cuddInt.c:14558
int garbageCollections
Definition: cuddInt.h:432
int populationSize
Definition: cuddInt.h:414
static int ddCountRoots(DdManager *table, int lower, int upper)
Definition: cuddInt.c:7021
int cuddNextLow(DdManager *table, int x)
Definition: cuddInt.c:15059
struct DdHashItem * next
Definition: cuddInt.h:281
static int zddUniqueCompareGroup(int *ptrX, int *ptrY)
Definition: cuddInt.c:26935
static int ddSiftingBackward(DdManager *table, int size, Move *moves)
Definition: cuddInt.c:16108
static int ddSecDiffCheck(DdManager *table, int x, int y)
Definition: cuddInt.c:10122
int cuddAnnealing(DdManager *table, int lower, int upper)
Definition: cuddInt.c:761
int cuddZddInitUniv(DdManager *zdd)
Definition: cuddInt.c:10668
void Mtr_FreeTree(MtrNode *node)
Definition: mtr.c:187
static int ddTreeSiftingAux(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddInt.c:8597
#define MTR_FIXED
Definition: mtr.h:97
static int ddGroupMove(DdManager *table, int x, int y, Move **moves)
Definition: cuddInt.c:9729
static int zddGroupSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddInt.c:27096
DdGen * Cudd_FirstCube(DdManager *dd, DdNode *f, int **cube, CUDD_VALUE_TYPE *value)
Definition: cuddInt.c:22267
DdNode * cuddZddSubset0(DdManager *dd, DdNode *P, int var)
Definition: cuddInt.c:31774
#define DD_ADD_ITE_TAG
Definition: cuddInt.h:173
#define ABC
#define DD_PLUS_INF_VAL
Definition: cuddInt.h:118
#define DD_BDD_MAX_EXP_TAG
Definition: cuddInt.h:191
#define DD_FIRST_REORDER
Definition: cuddInt.h:152
#define ADBC
st_generator * st_init_gen(st_table *)
Definition: st.c:606
int cuddZddGetPosVarIndex(DdManager *dd, int index)
Definition: cuddInt.c:26332
static int ddSymmSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddInt.c:18365
#define DCAB
Cudd_ReorderingType autoMethodZ
Definition: cuddInt.h:403
int bindVar
Definition: cuddInt.h:318
Definition: cuddInt.h:206
DdSubtable * subtables
Definition: cuddInt.h:349
static DdNode * background
Definition: cuddInt.c:22141
static int stopping_criterion(int c1, int c2, int c3, int c4, double temp)
Definition: cuddInt.c:912
static long shuffleTable[STAB_SIZE]
Definition: cuddInt.c:22146
int * permZ
Definition: cuddInt.h:370
double cachecollisions
Definition: cuddInt.h:437
#define DD_ZERO_VAL
Definition: cuddInt.h:109
DdNode * cuddZddWeakDiv(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:25528
static int ddGroupSiftingUp(DdManager *table, int y, int xLow, DD_CHKFP checkFunction, Move **moves)
Definition: cuddInt.c:9395
DdNode * DdNodePtr
Definition: cuddInt.h:253
void Mtr_ReorderGroups(MtrNode *treenode, int *permutation)
Definition: mtr.c:702
static int popsize
Definition: cuddInt.c:7451
static void cuddLocalCacheResize(DdLocalCache *cache)
Definition: cuddInt.c:12222
DdNode * value
Definition: cuddInt.h:257
#define DD_EPSILON
Definition: cuddInt.h:110
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddInt.c:15082
static int largest(void)
Definition: cuddInt.c:7968
struct MtrNode * parent
Definition: mtr.h:131
static void addVarToConst(DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero)
Definition: cuddInt.c:590
DdNode * cuddZddDiff(DdManager *zdd, DdNode *P, DdNode *Q)
Definition: cuddInt.c:31568
#define BETA
Definition: cuddInt.c:680
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddInt.c:14027
static int cuddZddSiftingAux(DdManager *table, int x, int x_low, int x_high)
Definition: cuddInt.c:30522
static Move * zddSwapAny(DdManager *table, int x, int y)
Definition: cuddInt.c:30366
void Cudd_SetMinHit(DdManager *dd, unsigned int hr)
Definition: cuddInt.c:1763
#define CBA
#define DD_DYN_RATIO
Definition: cuddInt.h:153
DdNode * cuddCacheLookup1Zdd(DdManager *table, DD_CTFP1 op, DdNode *f)
Definition: cuddInt.c:4699
static int cuddZddSiftingBackward(DdManager *table, Move *moves, int size)
Definition: cuddInt.c:30769
int cuddInitCache(DdManager *unique, unsigned int cacheSize, unsigned int maxCacheSize)
Definition: cuddInt.c:4198
#define MTR_DEFAULT
Definition: mtr.h:94
MtrNode * tree
Definition: cuddInt.h:408
double minHit
Definition: cuddInt.h:272
unsigned int keysize
Definition: cuddInt.h:268
struct DdSubtable DdSubtable
#define STAB_SIZE
Definition: cuddInt.c:22121
#define DD_MIN_HIT
Definition: cuddInt.h:137
static int numvars
Definition: cuddInt.c:7452
static void zddReorderPreprocess(DdManager *table)
Definition: cuddInt.c:30815
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddInt.c:20120
static int zddGroupSiftingUp(DdManager *table, int y, int xLow, Move **moves)
Definition: cuddInt.c:27245
struct MtrNode * elder
Definition: mtr.h:133
DdLocalCacheItem * item
Definition: cuddInt.h:266
long Cudd_ReadNodeCount(DdManager *dd)
Definition: cuddInt.c:1948
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
#define DD_DEFAULT_RECOMB
Definition: cuddInt.h:150
static int ddPickArbitraryMinterms(DdManager *dd, DdNode *node, int nvars, int nminterms, char **string)
Definition: cuddInt.c:23884
DD_HFP f
Definition: cuddInt.h:241
static int ddSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddInt.c:15809
#define MTR_TEST(node, flag)
Definition: mtr.h:150
DdNode ** deathRow
Definition: cuddInt.h:384
double cacheinserts
Definition: cuddInt.h:438
#define statLine(dd)
Definition: cuddInt.h:990
int cuddSifting(DdManager *table, int lower, int upper)
Definition: cuddInt.c:14824
DdNode ** stack
Definition: cuddInt.h:364
void(* DD_OOMFP)(long)
Definition: cudd.h:300
static Move * ddSiftingUp(DdManager *table, int y, int xLow)
Definition: cuddInt.c:15916
static int ddCheckPermuation(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddInt.c:16424
Cudd_VariableType
Definition: cudd.h:243
static Move * ddSwapAny(DdManager *table, int x, int y)
Definition: cuddInt.c:15668
static int cross
Definition: cuddInt.c:7467
int cuddZddSymmSiftingConv(DdManager *table, int lower, int upper)
Definition: cuddInt.c:32357
#define DD_SIFT_DOWN
Definition: cuddInt.c:8395
struct DdLocalCache * next
Definition: cuddInt.h:276
static void zddFindNodeHiLo(DdManager *table, MtrNode *treenode, int *lower, int *upper)
Definition: cuddInt.c:26860
static void debugFindParent(DdManager *table, DdNode *node)
Definition: cuddInt.c:5929
int Cudd_bddVarIsDependent(DdManager *dd, DdNode *f, DdNode *var)
Definition: cuddInt.c:2369
DdNode * cuddHashTableLookup2(DdHashTable *hash, DdNode *f, DdNode *g)
Definition: cuddInt.c:12050
static void ddClearFlag(DdNode *f)
Definition: cuddInt.c:23821
#define CUDD_GEN_NONEMPTY
Definition: cuddInt.h:199
#define STOREDD(i, j)
Definition: cuddInt.c:7476
static void ddUpdateInteract(DdManager *table, char *support)
Definition: cuddInt.c:11103
struct DdNode DdNode
Definition: cudd.h:256
#define DD_MINUS_INFINITY(dd)
Definition: cuddInt.h:908
#define MODULUS1
Definition: cuddInt.c:22113
#define cuddV(node)
Definition: cuddInt.h:641
unsigned int maxslots
Definition: cuddInt.h:274
static int ddVarGroupCheck(DdManager *table, int x, int y)
Definition: cuddInt.c:10329
unsigned long Cudd_ReadMemoryInUse(DdManager *dd)
Definition: cuddInt.c:1925
int st_insert(st_table *, void *, void *)
Definition: st.c:343
static Move * cuddZddLinearUp(DdManager *table, int y, int xLow, Move *prevMoves)
Definition: cuddInt.c:29177
static void freeMatrix(DdHalfWord **matrix)
Definition: cuddInt.c:6807
#define DD_INLINE
Definition: cuddInt.h:91
unsigned int countDead
Definition: cuddInt.h:407
int cuddHashTableInsert3(DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h, DdNode *value, ptrint count)
Definition: cuddInt.c:12106
DdNode * cuddZddChangeAux(DdManager *zdd, DdNode *P, DdNode *zvar)
Definition: cuddInt.c:31650
static int sift_up(DdManager *table, int x, int x_low)
Definition: cuddInt.c:7861
DdNode * cuddCofactorRecur(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:6226
struct MtrNode * younger
Definition: mtr.h:134
unsigned int initSlots
Definition: cuddInt.h:363
int cuddExact(DdManager *table, int lower, int upper)
Definition: cuddInt.c:6474
#define MV_OOM
Definition: cuddInt.c:17842
unsigned int randomizeOrder
Definition: cuddInt.h:416
#define DBCA
#define CABD
Cudd_VariableType varType
Definition: cuddInt.h:320
int reordered
Definition: cuddInt.h:392
unsigned int nextDyn
Definition: cuddInt.h:406
void cuddCacheResize(DdManager *table)
Definition: cuddInt.c:4955
#define DD_GC_FRAC_HI
Definition: cuddInt.h:135
void cuddSetInteract(DdManager *table, int x, int y)
Definition: cuddInt.c:10882
unsigned int dead
Definition: cuddInt.h:355
static int ddLinearAndSiftingBackward(DdManager *table, int size, Move *moves)
Definition: cuddInt.c:13752
static Move * ddLinearAndSiftingUp(DdManager *table, int y, int xLow, Move *prevMoves)
Definition: cuddInt.c:13516
int Cudd_EqualSupNorm(DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE tolerance, int pr)
Definition: cuddInt.c:17044
static int PMX(int maxvar)
Definition: cuddInt.c:8138
static int find_best(void)
Definition: cuddInt.c:8080
double Cudd_CountMinterm(DdManager *manager, DdNode *node, int nvars)
Definition: cuddInt.c:22209
#define NIL(type)
Definition: util.h:44
void Cudd_FreeZddTree(DdManager *dd)
Definition: cuddInt.c:1831
unsigned int cacheSlots
Definition: cuddInt.h:337
int Cudd_PrintLinear(DdManager *table)
Definition: cuddInt.c:12695
#define Cudd_IsComplement(node)
Definition: cudd.h:401
#define BACD
void cuddPrintVarGroups(DdManager *dd, MtrNode *root, int zdd, int silent)
Definition: cuddInt.c:5866
static int zddTotalNumberLinearTr
Definition: cuddInt.c:28566
unsigned int maxLive
Definition: cuddInt.h:357
int cuddNextHigh(DdManager *table, int x)
Definition: cuddInt.c:15037
static void zddVarToConst(DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty)
Definition: cuddInt.c:31961
CUDD_VALUE_TYPE value
Definition: cudd.h:269
int recomb
Definition: cuddInt.h:411
int cuddGa(DdManager *table, int lower, int upper)
Definition: cuddInt.c:7533
DdNode sentinel
Definition: cuddInt.h:328
#define CDAB
static int ddReorderPreprocess(DdManager *table)
Definition: cuddInt.c:16147
char * stash
Definition: cuddInt.h:382
MtrHalfWord index
Definition: mtr.h:130
#define STAB_DIV
Definition: cuddInt.c:22122
DdNode *(* DD_CTFP)(DdManager *, DdNode *, DdNode *)
Definition: cudd.h:297
DdNode ** stack
Definition: cuddInt.h:225
DdNode * cuddBddIteRecur(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:3380
Cudd_HookType
Definition: cudd.h:195
DdHook * postReorderingHook
Definition: cuddInt.h:422
static void ddFindNodeHiLo(DdManager *table, MtrNode *treenode, int *lower, int *upper)
Definition: cuddInt.c:8853
void cuddSlowTableGrowth(DdManager *unique)
Definition: cuddInt.c:21237
static void fixVarTree(MtrNode *treenode, int *perm, int size)
Definition: cuddInt.c:2126
DdNode * cuddCacheLookup2Zdd(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g)
Definition: cuddInt.c:4645
unsigned int keys
Definition: cuddInt.h:353
char * memset()
#define BADC
unsigned int itemsize
Definition: cuddInt.h:267
static Move * ddLinearAndSiftingDown(DdManager *table, int x, int xHigh, Move *prevMoves)
Definition: cuddInt.c:13639
#define ALLOC(type, num)
Definition: util.h:76
CUDD_VALUE_TYPE Cudd_ReadEpsilon(DdManager *dd)
Definition: cuddInt.c:1883
unsigned int dead
Definition: cuddInt.h:316
void Cudd_IterDerefBdd(DdManager *table, DdNode *n)
Definition: cuddInt.c:14090
FILE * out
Definition: cuddInt.h:423
static int computeLB(DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level)
Definition: cuddInt.c:7134
DdNode * cuddCacheLookup2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g)
Definition: cuddInt.c:4537
unsigned int flags
Definition: cuddInt.h:472
#define WEIGHT(weight, col)
Definition: cuddInt.c:16568
static void cuddZddSymmSummary(DdManager *table, int lower, int upper, int *symvars, int *symgroups)
Definition: cuddInt.c:33613
#define ACB
#define DD_SIFT_MAX_SWAPS
Definition: cuddInt.h:149
static DD_INLINE unsigned int ddLCHash(DdNodePtr *key, unsigned int keysize, int shift)
Definition: cuddInt.c:12304
int realignZ
Definition: cuddInt.h:405
DdCache * cache
Definition: cuddInt.h:336
int cuddZddGetPosVarLevel(DdManager *dd, int index)
Definition: cuddInt.c:26374
static int ddLinearUniqueCompare(int *ptrX, int *ptrY)
Definition: cuddInt.c:13382
static void bddFixTree(DdManager *table, MtrNode *treenode)
Definition: cuddInt.c:16331
double hits
Definition: cuddInt.h:273
DdHalfWord x
Definition: cuddInt.h:470
DdNode * next
Definition: cudd.h:267
void Cudd_Quit(DdManager *unique)
Definition: cuddInt.c:10641
static int cuddEstimateCofactor(DdManager *dd, st_table *table, DdNode *node, int i, int phase, DdNode **ptr)
Definition: cuddInt.c:23328
#define DD_GC_FRAC_LO
Definition: cuddInt.h:134
double lookUps
Definition: cuddInt.h:271
unsigned int numBuckets
Definition: cuddInt.h:294
int cuddHeapProfile(DdManager *dd)
Definition: cuddInt.c:5758
DdManager * manager
Definition: cuddInt.h:207
Cudd_LazyGroupType varToBeGrouped
Definition: cuddInt.h:323
struct DdGen::@1::@4 primes
#define CUDD_SWAP_MOVE
Definition: cuddInt.c:28542
#define DD_NORMAL_SIFT
Definition: cuddInt.c:8391
static void cuddLocalCacheAddToList(DdLocalCache *cache)
Definition: cuddInt.c:12333
double totCacheMisses
Definition: cuddInt.h:436
unsigned int slots
Definition: cuddInt.h:269
int maxSize
Definition: cuddInt.h:347
#define ddAbs(x)
Definition: cuddInt.h:799
void Cudd_Ref(DdNode *n)
Definition: cuddInt.c:14002
static void ddPatchTree(DdManager *dd, MtrNode *treenode)
Definition: cuddInt.c:21899
static int array_hash(char *array, int modulus)
Definition: cuddInt.c:8018
int cuddZddSifting(DdManager *table, int lower, int upper)
Definition: cuddInt.c:30268
int cuddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddInt.c:14926
static int ddResizeTable(DdManager *unique, int index, int amount)
Definition: cuddInt.c:21378
long * interact
Definition: cuddInt.h:377
int Cudd_GenFree(DdGen *gen)
Definition: cuddInt.c:22814
int cuddZddUniqueCompare(int *ptr_x, int *ptr_y)
Definition: cuddInt.c:29860
int cuddLinearInPlace(DdManager *table, int x, int y)
Definition: cuddInt.c:12874
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddInt.c:29836
#define DD_BDD_XOR_EXIST_ABSTRACT_TAG
Definition: cuddInt.h:175
unsigned int maxKeys
Definition: cuddInt.h:315
int(* DD_HFP)(DdManager *, const char *, void *)
Definition: cudd.h:292
static Move * cuddZddSymmSifting_down(DdManager *table, int x, int x_high, int initial_size)
Definition: cuddInt.c:33280
long * linear
Definition: cuddInt.h:378
#define DD_P2
Definition: cuddInt.h:157
static int ddEpdCountMintermAux(DdNode *node, EpDouble *max, EpDouble *epd, st_table *table)
Definition: cuddInt.c:23661
#define cuddIsConstant(node)
Definition: cuddInt.h:593
static void ddSupportStep(DdNode *f, int *support)
Definition: cuddInt.c:23792
int gcEnabled
Definition: cuddInt.h:360
#define MTR_NEWNODE
Definition: mtr.h:98
#define ddMax(x, y)
Definition: cuddInt.h:785
int cuddZddLinearSifting(DdManager *table, int lower, int upper)
Definition: cuddInt.c:28625
static int updateUB(DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper)
Definition: cuddInt.c:6979
static void ddFindSupport(DdManager *dd, DdNode *f, int *SP)
Definition: cuddInt.c:23953
int symmviolation
Definition: cuddInt.h:412
int cuddZddGetCofactors2(DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0)
Definition: cuddInt.c:26254
int numberXovers
Definition: cuddInt.h:415
static Move * ddSymmSiftingDown(DdManager *table, int x, int xHigh)
Definition: cuddInt.c:19066
unsigned long getSoftDataLimit(void)
Definition: util.c:198
#define CUDD_CONST_INDEX
Definition: cudd.h:107
int Cudd_NextCube(DdGen *gen, int **cube, CUDD_VALUE_TYPE *value)
Definition: cuddInt.c:22386
double cacheLastInserts
Definition: cuddInt.h:439
static Move * ddSymmSiftingUp(DdManager *table, int y, int xLow)
Definition: cuddInt.c:18924
#define DD_ADD_EVAL_CONST_TAG
Definition: cuddInt.h:186
static int cuddZddLinearInPlace(DdManager *table, int x, int y)
Definition: cuddInt.c:28728
static void ddCreateGroup(DdManager *table, int x, int y)
Definition: cuddInt.c:9156
static int updateEntry(DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper)
Definition: cuddInt.c:7201
DdNode ** nodelist
Definition: cuddInt.h:311
static int ddReorderPostprocess(DdManager *table)
Definition: cuddInt.c:16185
int linearSize
Definition: cuddInt.h:376
#define DD_LAZY_SIFT
Definition: cuddInt.c:8392
DdNode * cuddZddUnion(DdManager *zdd, DdNode *P, DdNode *Q)
Definition: cuddInt.c:31404
static int bddCheckPositiveCube(DdManager *manager, DdNode *cube)
Definition: cuddInt.c:2791
DdNode * cuddZddProduct(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:25147
double cacheHits
Definition: cuddInt.h:340
static int zddReorderChildren(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddInt.c:26759
#define DACB
#define CUDD_INVERSE_TRANSFORM_MOVE
Definition: cuddInt.c:28544
void cuddLocalCacheClearDead(DdManager *manager)
Definition: cuddInt.c:11362
DdNode * Cudd_bddMakePrime(DdManager *dd, DdNode *cube, DdNode *f)
Definition: cuddInt.c:17112
unsigned int maxsize
Definition: cuddInt.h:297
#define Cudd_Complement(node)
Definition: cudd.h:387
#define ddMin(x, y)
Definition: cuddInt.h:771
MtrHalfWord low
Definition: mtr.h:128
DdLocalCache * localCaches
Definition: cuddInt.h:417
static st_table * computed
Definition: cuddInt.c:7462
#define DD_BDD_ITE_TAG
Definition: cuddInt.h:176
#define DD_MAX_CACHE_TO_SLOTS_RATIO
Definition: cuddInt.h:145
DdNode * Cudd_Decreasing(DdManager *dd, DdNode *f, int i)
Definition: cuddInt.c:16691
#define ZDD_MV_OOM
Definition: cuddInt.c:32055
int cuddResizeLinear(DdManager *table)
Definition: cuddInt.c:13314
int st_ptrcmp(const char *, const char *)
Definition: st.c:585
static int ddBddShortestPathUnate(DdManager *dd, DdNode *f, int *phases, st_table *table)
Definition: cuddInt.c:17730
#define LOGBPL
Definition: cuddInt.c:12625
DdNode * Cudd_bddOr(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:3181
int cacheSlack
Definition: cuddInt.h:342
long util_cpu_time(void)
Definition: util.c:34
DdNode * cuddBddMakePrime(DdManager *dd, DdNode *cube, DdNode *f)
Definition: cuddInt.c:17148
st_retval
Definition: st.h:78
DdNode * cuddHashTableLookup3(DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:12162
static int ddWindowConv3(DdManager *table, int low, int high)
Definition: cuddInt.c:24484
#define cuddT(node)
Definition: cuddInt.h:609
#define DD_ZDD_ITE_TAG
Definition: cuddInt.h:184
DdNode * cuddAddIteRecur(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:410
CUDD_VALUE_TYPE value
Definition: cuddInt.c:19538
DdNode * cuddZddIntersect(DdManager *zdd, DdNode *P, DdNode *Q)
Definition: cuddInt.c:31493
DdNode * cuddZddUnateProduct(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:25384
DdNode * Cudd_ReadOne(DdManager *dd)
Definition: cuddInt.c:1716
int nextDead
Definition: cuddInt.h:386
void(* MMoutOfMemory)(long)
Definition: util.c:105
Definition: mtr.h:126
int varHandled
Definition: cuddInt.h:322
#define DD_BIGGY
Definition: cuddInt.c:16539
int Cudd_bddIsVarToBeGrouped(DdManager *dd, int index)
Definition: cuddInt.c:2067
#define BCAD
static long cuddRand2
Definition: cuddInt.c:22144
DdNode * cuddUniqueInterZdd(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddInt.c:20730
#define ACDB
static int roulette(int *p1, int *p2)
Definition: cuddInt.c:8258
#define ABDC
st_table * st_init_table(ST_PFICPCP, ST_PFICPI)
Definition: st.c:148
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:520
static int cuddZddLinearBackward(DdManager *table, int size, Move *moves)
Definition: cuddInt.c:29346
#define LEQQ2
Definition: cuddInt.c:22119
DdNode * cuddBddIntersectRecur(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:3518
#define ddCHash2(o, f, g, s)
Definition: cuddInt.h:741
#define CBAD
DdNode * cuddZddDivide(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:25926
DdNode * cuddZddSubset1(DdManager *dd, DdNode *P, int var)
Definition: cuddInt.c:31725
int zddTotalNumberSwapping
Definition: cuddInt.c:28565
int cuddLinearAndSifting(DdManager *table, int lower, int upper)
Definition: cuddInt.c:12750
static Move * ddJumpingUp(DdManager *table, int x, int x_low, int initial_size)
Definition: cuddInt.c:1182
DdGen * Cudd_FirstPrime(DdManager *dd, DdNode *l, DdNode *u, int **cube)
Definition: cuddInt.c:22497
static DdNode * zdd_subset0_aux(DdManager *zdd, DdNode *P, DdNode *zvar)
Definition: cuddInt.c:31891
static int rand_int(int a)
Definition: cuddInt.c:7997
#define DD_GC_FRAC_MIN
Definition: cuddInt.h:136
int Cudd_CheckKeys(DdManager *table)
Definition: cuddInt.c:5577
void cuddHashTableQuit(DdHashTable *hash)
Definition: cuddInt.c:11598
int cuddZddSymmSifting(DdManager *table, int lower, int upper)
Definition: cuddInt.c:32232
static cuddPathPair getShortest(DdNode *root, int *cost, int *support, st_table *visited)
Definition: cuddInt.c:17246
int Cudd_IsGenEmpty(DdGen *gen)
Definition: cuddInt.c:22854
static void ddClearGlobal2(DdManager *table)
Definition: cuddInt.c:11139
unsigned long GCTime
Definition: cuddInt.h:433
#define DD_BDD_LEQ_UNLESS_TAG
Definition: cuddInt.h:189
int Cudd_zddReduceHeap(DdManager *table, Cudd_ReorderingType heuristic, int minsize)
Definition: cuddInt.c:29608
#define ST_OUT_OF_MEM
Definition: st.h:41
#define ddEqualVal(x, y, e)
Definition: cuddInt.h:814
int cuddCacheProfile(DdManager *table, FILE *fp)
Definition: cuddInt.c:4815
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddInt.c:29885
#define ddLCHash1(f, shift)
Definition: cuddInt.c:11283
void cuddLocalCacheClearAll(DdManager *manager)
Definition: cuddInt.c:11414
#define MODULUS2
Definition: cuddInt.c:22117
DdNode ** memoryList
Definition: cuddInt.h:380
unsigned int maxReorderings
Definition: cuddInt.h:394
void cuddRehash(DdManager *unique, int i)
Definition: cuddInt.c:20917
unsigned int itemsize
Definition: cuddInt.h:290
static int cuddEstimateCofactorSimple(DdNode *node, int i)
Definition: cuddInt.c:23487
void Mtr_PrintGroups(MtrNode *root, int silent)
Definition: mtr.c:773
static int array_compare(const char *array1, const char *array2)
Definition: cuddInt.c:8050
void cuddPrintNode(DdNode *f, FILE *fp)
Definition: cuddInt.c:5829
unsigned long memused
Definition: cuddInt.h:429
void EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
Definition: epd.c:236
static int * storedd
Definition: cuddInt.c:7461
static int zddTreeSiftingAux(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddInt.c:26675
int siftMaxVar
Definition: cuddInt.h:395
static int zddGroupSifting(DdManager *table, int lower, int upper)
Definition: cuddInt.c:26963
int(* DD_CHKFP)(DdManager *, int, int)
Definition: cuddInt.c:8409
void Cudd_SetEpsilon(DdManager *dd, CUDD_VALUE_TYPE ep)
Definition: cuddInt.c:1904
int st_add_direct(st_table *, void *, void *)
Definition: st.c:395
#define DD_P1
Definition: cuddInt.h:156
#define cuddI(dd, index)
Definition: cuddInt.h:659
DdNode * cuddZddGetNode(DdManager *zdd, int id, DdNode *T, DdNode *E)
Definition: cuddInt.c:20408
static int restoreOrder(DdManager *table, int *array, int lower, int upper)
Definition: cuddInt.c:1395
int cuddZddAlignToBdd(DdManager *table)
Definition: cuddInt.c:29753
unsigned int ptruint
Definition: cuddInt.h:250
void cuddReclaimZdd(DdManager *table, DdNode *n)
Definition: cuddInt.c:14277
void cuddGetBranches(DdNode *g, DdNode **g1, DdNode **g0)
Definition: cuddInt.c:6196
int Cudd_bddReadPairIndex(DdManager *dd, int index)
Definition: cuddInt.c:2044
static int ddIsVarHandled(DdManager *dd, int index)
Definition: cuddInt.c:10417
int st_delete(st_table *, void *, void *)
Definition: st.c:437
DdHashTable * cuddHashTableInit(DdManager *manager, unsigned int keySize, unsigned int initSize)
Definition: cuddInt.c:11548
int cuddHashTableInsert2(DdHashTable *hash, DdNode *f, DdNode *g, DdNode *value, ptrint count)
Definition: cuddInt.c:11996
static int getLevelKeys(DdManager *table, int l)
Definition: cuddInt.c:6830
#define st_is_member(table, key)
Definition: st.h:107
#define CDBA
#define CUDD_VALUE_TYPE
Definition: cudd.h:87
static void ddDissolveGroup(DdManager *table, int x, int y)
Definition: cuddInt.c:10064
int Cudd_bddLeq(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:3283
int deathRowDepth
Definition: cuddInt.h:385
DdNode * nextFree
Definition: cuddInt.h:381
MtrNode * Mtr_InitGroupTree(int lower, int size)
Definition: mtr.c:410
static int ddExtSymmCheck(DdManager *table, int x, int y)
Definition: cuddInt.c:10179
static void ddClearGlobal(DdManager *table, int lower, int maxlevel)
Definition: cuddInt.c:7088
#define DD_MAX_SUBTABLE_SPARSITY
Definition: cuddInt.c:29525
#define BAC
#define DD_EQUIV_DC_TAG
Definition: cuddInt.h:183
int Cudd_ReadSize(DdManager *dd)
Definition: cuddInt.c:1787
int cuddZddSymmCheck(DdManager *table, int x, int y)
Definition: cuddInt.c:32127
static cuddPathPair getLargest(DdNode *root, st_table *visited)
Definition: cuddInt.c:17347
struct DdHook * next
Definition: cuddInt.h:242
static int ddGroupMoveBackward(DdManager *table, int x, int y)
Definition: cuddInt.c:9835
int cuddComputeFloorLog2(unsigned int value)
Definition: cuddInt.c:5102
void cuddCacheInsert(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)
Definition: cuddInt.c:4283
#define DD_DEFAULT_RESIZE
Definition: cuddInt.h:103
DdNode * cuddUniqueInterIVO(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddInt.c:20691
#define REALLOC(type, obj, num)
Definition: util.h:78
#define MAXGEN_RATIO
Definition: cuddInt.c:684
int Cudd_bddLeqUnless(DdManager *dd, DdNode *f, DdNode *g, DdNode *D)
Definition: cuddInt.c:16870
DdNode * key[1]
Definition: cuddInt.h:261
int cuddHashTableGenericInsert(DdHashTable *hash, DdNode *f, void *value)
Definition: cuddInt.c:11910
static int ddSymmSiftingBackward(DdManager *table, Move *moves, int size)
Definition: cuddInt.c:19356
struct DdGen::@1::@3 cubes
static int zddGroupMoveBackward(DdManager *table, int x, int y)
Definition: cuddInt.c:27514
DdNode * Cudd_zddDiffConst(DdManager *zdd, DdNode *P, DdNode *Q)
Definition: cuddInt.c:31212
int Cudd_NextNode(DdGen *gen, DdNode **node)
Definition: cuddInt.c:22782
#define LEQA1
Definition: cuddInt.c:22114
VOID_OR_INT abort()
DdNode * Cudd_bddExistAbstract(DdManager *manager, DdNode *f, DdNode *cube)
Definition: cuddInt.c:2331
#define CUDD_GEN_EMPTY
Definition: cuddInt.h:198
int sizeZ
Definition: cuddInt.h:346
DdNode * cuddZddIsop(DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I)
Definition: cuddInt.c:27794
DdHalfWord index
Definition: cudd.h:265
int cuddZddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddInt.c:30147
DdHashItem * nextFree
Definition: cuddInt.h:292
unsigned int looseUpTo
Definition: cuddInt.h:361
int cuddSymmCheck(DdManager *table, int x, int y)
Definition: cuddInt.c:17912
void EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
Definition: epd.c:302
unsigned int slots
Definition: cuddInt.h:313
static int result
Definition: cuddInt.c:7466
DdHalfWord y
Definition: cuddInt.h:471
static int ddGroupSiftingDown(DdManager *table, int x, int xHigh, DD_CHKFP checkFunction, Move **moves)
Definition: cuddInt.c:9553
unsigned int reorderings
Definition: cuddInt.h:393
DdNode ** vars
Definition: cuddInt.h:373
double cacheMisses
Definition: cuddInt.h:339
DdNode * Cudd_bddAndLimit(DdManager *dd, DdNode *f, DdNode *g, unsigned int limit)
Definition: cuddInt.c:3146
DdNode * cuddZddWeakDivF(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:25689
void Cudd_FreeTree(DdManager *dd)
Definition: cuddInt.c:1807
unsigned long maxmemhard
Definition: cuddInt.h:431
static int ddSymmGroupMoveBackward(DdManager *table, int x, int y)
Definition: cuddInt.c:19285
DdHook * postGCHook
Definition: cuddInt.h:420
static void cuddLocalCacheRemoveFromList(DdLocalCache *cache)
Definition: cuddInt.c:12357
int pairIndex
Definition: cuddInt.h:321
int cuddZddGetNegVarLevel(DdManager *dd, int index)
Definition: cuddInt.c:26395
DdNode *(* DD_CTFP1)(DdManager *, DdNode *)
Definition: cudd.h:298
#define CUDD_GEN_CUBES
Definition: cuddInt.h:194
static double random_generator(void)
Definition: cuddInt.c:942
double minHit
Definition: cuddInt.h:341
#define DD_MAX_REORDER_GROWTH
Definition: cuddInt.h:151
static void ddReportRefMess(DdManager *unique, int i, const char *caller)
Definition: cuddInt.c:21976
static int ddUpdateMtrTree(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddInt.c:16365
int cuddHashTableInsert(DdHashTable *hash, DdNodePtr *key, DdNode *value, ptrint count)
Definition: cuddInt.c:11684
static int ddSetVarHandled(DdManager *dd, int index)
Definition: cuddInt.c:10369
void EpdMakeZero(EpDouble *epd, int sign)
Definition: epd.c:555
void Cudd_Srandom(long seed)
Definition: cuddInt.c:22943
static int ddWindow4(DdManager *table, int low, int high)
Definition: cuddInt.c:24838
#define cuddClean(p)
Definition: cuddInt.h:757
static int ddNoCheck(DdManager *table, int x, int y)
Definition: cuddInt.c:10098
DdManager * cuddInitTable(unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo)
Definition: cuddInt.c:19738
static int ddSymmUniqueCompare(int *ptrX, int *ptrY)
Definition: cuddInt.c:18337
union DdGen::@1 gen
CUDD_VALUE_TYPE epsilon
Definition: cuddInt.h:390
static int ddWindow3(DdManager *table, int low, int high)
Definition: cuddInt.c:24437
DdNode * one
Definition: cuddInt.h:329
unsigned int next
Definition: cuddInt.h:317
void * cuddHashTableGenericLookup(DdHashTable *hash, DdNode *f)
Definition: cuddInt.c:11957
static int cuddZddLinearAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddInt.c:29050
void cuddClearDeathRow(DdManager *table)
Definition: cuddInt.c:14365
EpDouble * EpdAlloc(void)
Definition: epd.c:71
static int ddJumpingAux(DdManager *table, int x, int x_low, int x_high, double temp)
Definition: cuddInt.c:1111
#define CUDD_MAXINDEX
Definition: cudd.h:102
MtrNode * treeZ
Definition: cuddInt.h:409
int autoDynZ
Definition: cuddInt.h:401
static DdNode * ddBddMaximallyExpand(DdManager *dd, DdNode *lb, DdNode *ub, DdNode *f)
Definition: cuddInt.c:17521
int cacheShift
Definition: cuddInt.h:338
#define cuddE(node)
Definition: cuddInt.h:625
#define Cudd_NotCond(node, c)
Definition: cudd.h:359
DdNode * Cudd_bddOrLimit(DdManager *dd, DdNode *f, DdNode *g, unsigned int limit)
Definition: cuddInt.c:3214
struct Move * next
Definition: cuddInt.h:474
#define DD_PLUS_INFINITY(dd)
Definition: cuddInt.h:894
int Cudd_DebugCheck(DdManager *table)
Definition: cuddInt.c:5255
static int build_dd(DdManager *table, int num, int lower, int upper)
Definition: cuddInt.c:7897
DdNode * plusinfinity
Definition: cuddInt.h:331
static int cuddZddSymmSiftingAux(DdManager *table, int x, int x_low, int x_high)
Definition: cuddInt.c:32543
void Cudd_RecursiveDerefZdd(DdManager *table, DdNode *n)
Definition: cuddInt.c:14145
static int addMultiplicityGroups(DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask)
Definition: cuddInt.c:2169
static int zddShuffle(DdManager *table, int *permutation)
Definition: cuddInt.c:30939
#define cuddSatDec(x)
Definition: cuddInt.h:849
static int large
Definition: cuddInt.c:7464
static int cuddZddSymmSiftingConvAux(DdManager *table, int x, int x_low, int x_high)
Definition: cuddInt.c:32883
DdNode * key[1]
Definition: cuddInt.h:284
static int ddSiftUp(DdManager *table, int x, int xLow)
Definition: cuddInt.c:6944
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInt.c:10917
void Cudd_Deref(DdNode *node)
Definition: cuddInt.c:14198
int Cudd_NextPrime(DdGen *gen, int **cube)
Definition: cuddInt.c:22599
static int ddSymmSiftingConvAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddInt.c:18667
static int ddResetVarHandled(DdManager *dd, int index)
Definition: cuddInt.c:10393
int arcviolation
Definition: cuddInt.h:413
void Cudd_OutOfMem(long size)
Definition: cuddInt.c:22982
#define JUMP_UP_PROB
Definition: cuddInt.c:683
#define bang(f)
Definition: cuddInt.c:22152
int st_ptrhash(char *, int)
Definition: st.c:547
static double ddCountPathAux(DdNode *node, st_table *table)
Definition: cuddInt.c:23600
int cuddWindowReorder(DdManager *table, int low, int high, Cudd_ReorderingType submethod)
Definition: cuddInt.c:24123
DdNode * cuddBddBooleanDiffRecur(DdManager *manager, DdNode *f, DdNode *var)
Definition: cuddInt.c:2719
int Cudd_CheckCube(DdManager *dd, DdNode *g)
Definition: cuddInt.c:6155
#define ddLCHash2(f, g, shift)
Definition: cuddInt.c:11304
static int * entry
Definition: cuddInt.c:8422
int shift
Definition: cuddInt.h:295
int * invperm
Definition: cuddInt.h:371
static DdNode * zero
Definition: cuddInt.c:16562
DdSubtable constants
Definition: cuddInt.h:351
double cachedeletions
Definition: cuddInt.h:440
int Cudd_addLeq(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:341
void cuddCacheFlush(DdManager *table)
Definition: cuddInt.c:5070
DdNode * cuddBddXorRecur(DdManager *manager, DdNode *f, DdNode *g)
Definition: cuddInt.c:3761
int isolated
Definition: cuddInt.h:368
static int ddWindowConv2(DdManager *table, int low, int high)
Definition: cuddInt.c:24249
#define STOP_TEMP
Definition: cuddInt.c:685
static DdNode * getCube(DdManager *manager, st_table *visited, DdNode *f, int cost)
Definition: cuddInt.c:17435
unsigned long maxmem
Definition: cuddInt.h:430
static int ddPermuteWindow3(DdManager *table, int x)
Definition: cuddInt.c:24342
static Move * cuddZddLinearDown(DdManager *table, int x, int xHigh, Move *prevMoves)
Definition: cuddInt.c:29262
DdNode * minusinfinity
Definition: cuddInt.h:332
int ddTotalNumberSwapping
Definition: cuddInt.c:14489
#define DD_MEM_CHUNK
Definition: cuddInt.h:105
struct cuddPathPair cuddPathPair
static int ddWindowConv4(DdManager *table, int low, int high)
Definition: cuddInt.c:24885
int Cudd_RemoveHook(DdManager *dd, DD_HFP f, Cudd_HookType where)
Definition: cuddInt.c:1991
MtrNode * Mtr_MakeGroup(MtrNode *root, unsigned int low, unsigned int high, unsigned int flags)
Definition: mtr.c:446
int cuddResizeTableZdd(DdManager *unique, int index)
Definition: cuddInt.c:21093
static int zddGroupMove(DdManager *table, int x, int y, Move **moves)
Definition: cuddInt.c:27408
static DdNode * zdd_subset1_aux(DdManager *zdd, DdNode *P, DdNode *zvar)
Definition: cuddInt.c:31822
DdHashItem ** memoryList
Definition: cuddInt.h:293
DdNode * Cudd_bddIthVar(DdManager *dd, int i)
Definition: cuddInt.c:1685
DdNode * Cudd_bddIteConstant(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:2974
#define cuddAdjust(x)
Definition: cuddInt.h:932
int autoDyn
Definition: cuddInt.h:400
static int checkSymmInfo(DdManager *table, DdHalfWord *symmInfo, int index, int level)
Definition: cuddInt.c:7329
#define DD_ONE(dd)
Definition: cuddInt.h:864
int shift
Definition: cuddInt.h:312
DdNode * cuddAddCmplRecur(DdManager *dd, DdNode *f)
Definition: cuddInt.c:527
DdCache * acache
Definition: cuddInt.h:335
static void ddSymmSummary(DdManager *table, int lower, int upper, int *symvars, int *symgroups)
Definition: cuddInt.c:19400
DdManager * manager
Definition: cuddInt.h:275
unsigned int keysZ
Definition: cuddInt.h:354
DdNode * cuddBddAndRecur(DdManager *manager, DdNode *f, DdNode *g)
Definition: cuddInt.c:3633
static int ddPermuteWindow4(DdManager *table, int w)
Definition: cuddInt.c:24582
DdNode * cuddZddDivideF(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:26026
void EpdCopy(EpDouble *from, EpDouble *to)
Definition: epd.c:600
DdHook * preGCHook
Definition: cuddInt.h:419
#define CUDD_LINEAR_TRANSFORM_MOVE
Definition: cuddInt.c:28543
int Cudd_ReadPerm(DdManager *dd, int i)
Definition: cuddInt.c:1859
static DdHalfWord * initSymmInfo(DdManager *table, int lower, int upper)
Definition: cuddInt.c:7293
DdNode * Cudd_addEvalConst(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:225
Cudd_ReorderingType
Definition: cudd.h:141
long Cudd_Random(void)
Definition: cuddInt.c:22881
#define DD_MINUS_INF_VAL
Definition: cuddInt.h:122
void cuddFreeTable(DdManager *unique)
Definition: cuddInt.c:20050
static void ddRehashZdd(DdManager *unique, int i)
Definition: cuddInt.c:21274
static int zddReorderPostprocess(DdManager *table)
Definition: cuddInt.c:30844
static int cuddHashTableResize(DdHashTable *hash)
Definition: cuddInt.c:12392
#define CUDD_GEN_PRIMES
Definition: cuddInt.h:195
DdNode * cuddHashTableLookup1(DdHashTable *hash, DdNode *f)
Definition: cuddInt.c:11855
static int cuddZddSymmSiftingBackward(DdManager *table, Move *moves, int size)
Definition: cuddInt.c:33371
static long cuddRand
Definition: cuddInt.c:22143
Cudd_LazyGroupType
Definition: cudd.h:228
DdNode * cuddZddComplement(DdManager *dd, DdNode *node)
Definition: cuddInt.c:26289
struct MtrNode * child
Definition: mtr.h:132
int * perm
Definition: cuddInt.h:369
unsigned long timeLimit
Definition: cuddInt.h:427
struct DdCache DdCache
int size
Definition: cuddInt.h:473
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
DdNode * cuddZddIte(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddInt.c:31278
unsigned int minDead
Definition: cuddInt.h:358
static int cuddNodeArrayRecur(DdNode *f, DdNodePtr *table, int index)
Definition: cuddInt.c:23288
static int ddShuffle2(DdManager *table, int *permutation)
Definition: cuddInt.c:16218
DdNode * cuddMakeBddFromZddCover(DdManager *dd, DdNode *node)
Definition: cuddInt.c:28360
DdNode * cuddBddXorExistAbstractRecur(DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)
Definition: cuddInt.c:2547
int cuddInitLinear(DdManager *table)
Definition: cuddInt.c:13269
#define cuddSatInc(x)
Definition: cuddInt.h:831
#define LEQR2
Definition: cuddInt.c:22120
static int dp2(DdManager *dd, DdNode *f, st_table *t)
Definition: cuddInt.c:23106
DdNode * cuddZddGetNodeIVO(DdManager *dd, int index, DdNode *g, DdNode *h)
Definition: cuddInt.c:20441
#define MTR_SOFT
Definition: mtr.h:96
int Cudd_bddIsVarToBeUngrouped(DdManager *dd, int index)
Definition: cuddInt.c:2096
void cuddCacheInsert2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g, DdNode *data)
Definition: cuddInt.c:4329
int cuddSymmSifting(DdManager *table, int lower, int upper)
Definition: cuddInt.c:18042
double reclaimed
Definition: cuddInt.h:367
void cuddReclaim(DdManager *table, DdNode *n)
Definition: cuddInt.c:14223
int cuddZddP(DdManager *zdd, DdNode *f)
static long shuffleSelect
Definition: cuddInt.c:22145
DdNode * background
Definition: cuddInt.h:333
#define EXC_PROB
Definition: cuddInt.c:682
int status
Definition: cuddInt.h:209
DdNode * Cudd_bddIntersect(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:3082
int cuddZddGetNegVarIndex(DdManager *dd, int index)
Definition: cuddInt.c:26353
DdSubtable * subtableZ
Definition: cuddInt.h:350
double totCachehits
Definition: cuddInt.h:435
void cuddZddFreeUniv(DdManager *zdd)
Definition: cuddInt.c:10717
DdNode ** univ
Definition: cuddInt.h:375
static int * repeat
Definition: cuddInt.c:7463
DdNode * Cudd_Cofactor(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddInt.c:6119
static int zdd_group_move_backward(DdManager *table, int x, int y)
Definition: cuddInt.c:33530
if(DEFINED IN_SOURCE_BUILD) set(LLVM_LINK_COMPONENTS BitWriter Core IPO IrReader InstCombine Instrumentation Target Linker Analysis ScalarOpts Support Svf Cudd) add_llvm_tool(dvf dda.cpp) else() add_executable(dvf dda.cpp) target_link_libraries(dvf Svf Cudd $
Definition: CMakeLists.txt:2
#define DD_NON_CONSTANT
Definition: cuddInt.h:124
static DdNode * cuddUniqueLookup(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddInt.c:23428
#define DD_ZERO(dd)
Definition: cuddInt.h:880
DdNodePtr * cuddNodeArray(DdNode *f, int *n)
Definition: cuddInt.c:23067